Python中的repr与的str

在学习UCB的CS61a时遇到了一个新的知识点,就是python中repr与str的区别:

总体上来说,这两者在性能和表现上非常相似;

repr返回的是一个对象的更加明确的字符串表示;

str则致力于返回一个通读易懂的字符串表示;

  • 借用stackoverflow的一句话:My rule of thumb: __repr__ is for developers, __str__ is for customers.

str()与repr()

首先来看内置函数str()与repr(),str()致力于为用户的最终输出,而repr()则经常用来调试和开发。repr()计算一个对象的“官方”的字符串表示(一个具有关于该对象的所有信息的表示),而str()用于计算一个对象的“非正式”字符串表示形式(用于打印目的)。

举个例子:

1
2
3
4
5
6
7
8
9
10
>>> s = 'Hello, world.'
>>> str(s)
'Hello, world.'
>>> repr(s)
"'Hello, world.'"
>>> str(str(s))
'Hello, world.'
>>> repr(repr(s))
'"\'Hello, world.\'"'
>>> eval(eval(repr(repr(s))))

eval()可以执行repr返回字符串里面的对象。


类中的__str__与__repr__

我们先来测试一下,可见在这种情况,打印出来的类信息都是一样的,除了object的id之外别无它物。而且类中也有内置的method——repr和str。

1
2
3
4
5
6
7
8
9
10
11
12
>>> class Test(object): pass
...
>>> print(str(Test()))
<__main__.Test object at 0x000000BD373D86A0>
>>> print(repr(Sic()))
<__main__.Test object at 0x000000BD373D86A0>
>>> a = Test()
>>> a.__repr__()
<__main__.Test object at 0x000000BD373D86A0>
>>> a.__str__()
<__main__.Test object at 0x000000BD373D86A0>
>>>

接下来我根据课程上展示的代码来重载__repr__和__str__两个方法,输出结果如注释所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Bear():
"""docstring for Bear"""
"""
a bear
a bear
Bear()
my str
my repr
[Finished in 0.1s]
"""
def __init__(self):
self.__repr__ = lambda: 'my repr'
self.__str__ = lambda: 'my str'

def __repr__(self):
return 'Bear()'

def __str__(self):
return 'a bear'
oski = Bear()

print(oski)
print(str(oski))
print(repr(oski))
print(oski.str())
print(oski.repr())

通过对比发现,在只重载repr这个方法的时候,str()这个函数返回的也是类内置的方法repr的内容;

如果重载了str这个方法,str()函数返回的才是类内置方法str的内容;

也就是str中包含了repr的内容,也就是覆盖了str的表达,使其表达更为易懂;

大致使用方法如下:

1
2
3
4
5
6
7
8
def repr(x):
return type(x).__repr__(x)
def str(x):
t = type(x)
if hasattr(t, '__str__'):
return t.__str__(x)
else:
return repr(x)


总结

尽量在类中实现重载repr的方法,使其成为继init之后的第二个性质,以便开发者明白这是怎么实现的;如果你希望在面对用户而不是开发人员时使用更为pretty的表达,就实现str的方法,这是可选的。