__str__与__repr__区别

首先通过代码来对比一下 str repr

只存在 str:

1
2
3
4
5
6
7
8
9
class DisplayTest:
def __str__(self):
return 'output_by_str'

>>> test = DisplayTest()
>>> test
<DisplayTest object at 0x000002A101128940>
>>> print(test)
output_by_str

只存在 repr:

1
2
3
4
5
6
7
8
class DisplayTest:
def __repr__(self):
return 'output_by_repr'
>>> test = DisplayTest()
>>> test
output_by_repr
>>> print(test)
output_by_repr

同时存在 str repr:

1
2
3
4
5
6
7
8
9
10
class DisplayTest:
def __str__(self):
return 'output_by_str'
def __repr__(self):
return 'output_by_repr'
>>> test = DisplayTest()
>>> test
output_by_repr
>>> print(test)
output_by_str

从以上代码中可以看出,在控制台输出对象时会调用 repr 方法,在使用print进行输出打印时会优先调用 str 方法,如果没有 str 方法,就会去调用 repr 方法。

如果在自定义类中没有重构str,repr方法,就会使用object基类中str,repr方法,输出对象一些地址相关的信息如:

1
<DisplayTest object at 0x000002A101128940>

对于这两种方法,就像网上所说的那样, str 是面向用户, repr 是面向程序员的,比如:

1
2
3
4
5
>>> test = '你好'
>>> test
'你好'
>>> print(test)
你好
1
2
3
4
5
import datetima
>>> datetime.datetime.now()
datetime.datetime(2020, 2, 17, 23, 48, 37, 449751)
>>> print(datetime.datetime.now())
2020-02-17 23:48:47.938524

print输出的内容,更直观更容易理解一些,而直接使用终端输出的内容,让程序员更方便处理一些。

还需要注意的一点是,将对象放入容器中时,就算重构了 str 方法,进行print也是不会生效的,容器会使用 repr 中的返回值,比如:

1
2
3
4
5
6
7
class DisplayTest:
def __str__(self):
return 'output_by_str'
>>> test_1 = DisplayTest()
>>> test_2 = DisplayTest()
>>> print([test1, test2])
[<DisplayTest object at 0x000002A100BCA588>, <DisplayTest object at 0x000002A100EFE630>]
1
2
3
4
5
6
7
class DisplayTest:
def __repr__(self):
return 'output_by_repr'
>>> test_1 = DisplayTest()
>>> test_2 = DisplayTest()
>>> print([test1, test2])
[output_by_repr, output_by_repr]

大部分的内建函数都会通过str, repr来输出实质相同但显示不同的值,或许这是作者想让代码更加pythonic吧,为我们提供一种设计代码的标准。

对于我自己来说,我更愿意在自定义类中去只设定一个 repr ,因为它能同时兼顾终端输出和print输出,就像汽车的远光灯,同样具备近光灯的效果,但更远更亮。