__repr__
的作用输出实例对象时,其内容由
__repr__
的返回值决定
举个例子吧,通俗易懂
class Test:
def __repr__(self):
return '铁锤'
t = Test()
print(t) # 铁锤
可以看到,当打印实例对象的时候,打印的结果就是__repr__
的返回值。而我们如果不定义__repr__
则会默认使用object
的__repr__
函数,返回的东西大家应该也都很清楚了,像下面这样的:
<__main__.Test object at 0x000002004AD16D00>
从上面的例子看起来,实例对象t接收的好像就是__repr__
的返回值,那么他就应该是一个字符串啊;打印他的类型看一下:
print(t) # 铁锤
print(type(t)) # class '__main__.Test'>
这里python告诉我们t的值虽然是一个字符串铁锤
,但是他确实是一个实例对象。
那这不就矛盾了么,到底怎么回事呢?
我在文章Python 中的 __new__
中提到过,实例对象最终接收的是类中__new__
(即元类中__call__
)的返回值。那么为什么打印出来的是__repr__
的返回值呢?
接着往下看,做两个测试就懂了
测试一
class Test:
def __new__(cls):
return '砖头'
def __repr__(self):
return '铁锤'
t = Test()
print(t) # 砖头
print(type(t)) #
由上面这个例子可以看到,实例对象t接受的确确实实是__new__
的返回值,无论是数值还是类型都对的上。(改成其他类型一样)
因此由上面这个例子可以断定:实例对象接收的是__new__
的返回值
文章中对于id()函数和内存存储的研究讲过,要想判断python中两个变量到底指的是不是一个东西,就用id看一下他的内存地址情况就晓得了。
测试二
class Test:
def __repr__(self):
return '铁锤'
t = Test()
print(t) # 铁锤
print(t.__repr__()) # 铁锤
print(id(t)) # 2115012947200
print(id(t.__repr__())) # 2115012857168
print(id('铁锤')) # 2115012857168
诶,是不是秒懂?其实当你打印实例对象的时候,python调用的其实是实例对象.__repr__()
,因此其实是调用了实例对象t的__repr__
方法,因此打印的结果和__repr__
的返回值相同,但是t确实__new__
返回的实例对象。
可以再用is来判断一下
print(t is t.__repr__()) # False
print('铁锤' is t.__repr__()) # True
打印实例对象的时候,其实python真正执行的语句是print(实例对象.__repr__())
;因此打印的结果其实是__repr__
的返回值,而实例对象接收的是__new__
的返回值
__str__
的作用如果你理解了__repr__
的作用以后,你就理解了__str__
的作用了。
即这两个成员的作用是一模一样的,只不过__str__
要更猛一点,当你的类中同时重写了__str__
和__repr__
后,那么当你打印实例对象的时候,python底层会优先执行实例对象.__str__()
class Test:
def __repr__(self):
return '铁锤'
def __str__(self):
return '砖头'
t = Test()
# 等效于 print(t.__str__())
print(t) # 砖头
通过上面这个例子可以看到,输出的是__str__
的返回值(__repr__
没抢过__str__
)。
那么__str__
和__repr__
有什么区别呢?
有些教程中会说__str__
是面向用户的,__repr__
是面向程序员的。
还是看两个例子
例子一:
In [12]: class Test:
...: def __repr__(self):
...: return '铁锤'
...:
...: def __str__(self):
...: return '砖头'
...:
In [13]: t = Test()
In [14]: t
Out[14]: 铁锤
In [15]: print(t)
砖头
例子二:
class Test:
def __repr__(self):
return '铁锤'
def __str__(self):
return '砖头'
t = Test()
还是这段代码,我们打开cmd,cd到这个py文件所在的路径以后,进入python环境
>>> from test import Test
>>> t = Test()
>>> t
铁锤
>>> print(t)
砖头
因此__repr__
和__str__
的区别就是:
当打印的时候python优先调用print(实例对象.__str__())
;而当在交互式界面直接敲实例对象的时候,python底层执行的其实是实例对象.__repr__()
。