魔术方法:__repr__(self) 和 __str__(self)
先看一个示例:
class?Tab:
????def?__init__(self):
????????self.color?=?"yellow"
a?=?Tab()
print(a)
运行结果如下:
<__main__.Tab?object?at?0x0000017FBADFFD08>
Process?finished?with?exit?code?0
从上述结果可以看出,输出的是类名和内存地址,可有些时候并不想要这些数据,想要color 属性还得再调用一次进行获取(a.color ),如遇到私有属性的话还拿不出来,所以就得优化输出,优化成不调用就可以看到信息:
class?Tab:
????def?__init__(self):
????????#?带下划线即为私有属性
????????self._color?=?"yellow"
????def?__repr__(self):
????????return?self._color
????def?__str__(self):
????????return?self._color
a?=?Tab()
print(a)
运行结果如下:
yellow
Process?finished?with?exit?code?0
上述代码中同时定义了 __repr__(self) 和 __str__(self) 两个魔术方法,它俩都可以实现类实例返回的内容
如果__repr__(self) 和 __str__(self) 两者同时存在的话就优先调用__str__(self) 后直接返回,如果没有__str__(self) ,只有 __repr__(self) 的话就执行后直接返回
__repr__(self) 和 __str__(self)应用场景
这两种魔术方法,就是处理类实例并返回字符串信息,我个人使用的场景多数用于自定义异常捕获、数据替换及类实例输出描述信息等
class?Base:
????def?__init__(self,
?????????????????var:?str,
?????????????????old:?str,
?????????????????new:?str,
?????????????????count:?int?=?0):
????????self._var,?self._old?=?var,?old
????????self._new,?self._count?=?new,?count
????def?__repr__(self):
????????if?self._count?==?0:
????????????self._count?=?len(self._var)
????????return?self._var.replace(self._old,?self._new,?self._count)
a?=?"bbb"
print(Base(a,?"b",?"2"))
运行结果如下:
222
Process?finished?with?exit?code?0
class?BaseError(Exception):
????pass
class?CustomError(BaseError):
????def?__init__(self,?message):
????????self._msg?=?message
????def?__repr__(self):
????????return?self._msg
try:
????assert?5?==?3
except?Exception?as?e:
????raise?CustomError("5不相等3")?from?e
运行结果如下:
Traceback?(most?recent?call?last):
??File?"F:/apiInterface/web/classify.py",?line?69,?in?<module>
????assert?5?==?3
AssertionError
The?above?exception?was?the?direct?cause?of?the?following?exception:
Traceback?(most?recent?call?last):
??File?"F://apiInterface/web/classify.py",?line?71,?in?<module>
????raise?CustomError("5不相等3")?from?e
__main__.CustomError:?5不相等3
Process?finished?with?exit?code?1
class?Base:
????def?__init__(self,
?????????????????var:?str,
?????????????????old:?str,
?????????????????new:?str,
?????????????????count:?int?=?0):
????????self._var,?self._old?=?var,?old
????????self._new,?self._count?=?new,?count
????def?__str__(self):
????????if?self._count?==?0:
????????????self._count?=?len(self._var)
????????return?self._var.replace(self._old,?self._new,?self._count)
class?BaseError(Exception):
????pass
class?CustomError(BaseError):
????def?__init__(self,?message):
????????self._msg?=?message
????def?__str__(self):
????????return?self._msg
从上述代码中可以看到__repr__(self) 和 __str__(self) 两种魔术方法都能实现对方一样的操作,由此可以断定两个方法实际是类似的,官方也有明确表示:实际object.__str__() 默认实现会调用 object.__repr__() 。
__repr__(self) 和 __str__(self)的对比
- 通俗点讲
__repr__(self) 通常多被开发用于调试,返回的信息准确性会强一些 - 通俗点讲
__str__(self) 返回更准确且可读性很强的描述信息
上述的一些代码中很难看出区别,所以引用了python 的时间库进行对比操作:
from?datetime?import?timedelta
c?=?timedelta(days=1)
print(c.__repr__())
print(c.__str__())
运行结果如下:
datetime.timedelta(days=1)
1?day,?0:00:00
Process?finished?with?exit?code?0
从运行结果可以清晰看到__repr__(self) 方法返回的是偏向开发者能看懂的数据,而 __str__(self) 方法返回的是可读性很强的数据
以上总结或许能帮助到你,或许帮助不到你,但还是希望能帮助到你,如有疑问、歧义,直接私信留言会及时修正发布;非常期待你的点赞和分享哟,谢谢!
未完,待续…
一直都在努力,希望您也是!
微信搜索公众号:就用python
文章作者:李 锋|编辑排版:梁莉莉
|