Python中__str__和__repr_之间有什么区别?


当前回答

老实说,eval(repr(obj))从不使用。如果你发现自己在使用它,你应该停止,因为eval是危险的,字符串是一种非常低效的序列化对象的方法(改用pickle)。

因此,我建议设置__repr_=__str__。原因是str(list)在元素上调用repr(我认为这是Python最大的设计缺陷之一,Python 3没有解决)。实际的repr可能对打印([your,objects])的输出没有太大帮助。

为了证明这一点,根据我的经验,repr函数最有用的用例是将一个字符串放在另一个字符串中(使用字符串格式)。这样,您就不必担心转义引号或其他任何问题。但请注意,这里没有eval。

其他回答

我的经验法则是:__repr_面向开发者,__str__面向客户。

摘自《流利的Python》一书:

Python对象的基本要求是提供可用的自身的字符串表示,用于调试和日志记录,另一个用于向最终用户演示。这就是为什么数据模型中存在特殊的方法repr_和str__。

除非您特别采取行动以确保其他情况,否则大多数类对以下两种情况都没有帮助:

>>> class Sic(object): pass
... 
>>> print(str(Sic()))
<__main__.Sic object at 0x8b7d0>
>>> print(repr(Sic()))
<__main__.Sic object at 0x8b7d0>
>>> 

正如您所看到的,没有区别,也没有超出类和对象id的信息。如果您只覆盖这两个中的一个…:

>>> class Sic(object): 
...   def __repr__(self): return 'foo'
... 
>>> print(str(Sic()))
foo
>>> print(repr(Sic()))
foo
>>> class Sic(object):
...   def __str__(self): return 'foo'
... 
>>> print(str(Sic()))
foo
>>> print(repr(Sic()))
<__main__.Sic object at 0x2617f0>
>>> 

如您所见,如果重写__repr_,那么它也用于__str__,但反之亦然。

要知道的其他关键提示:内置容器上的__str__使用__repr_而不是__str__来表示它包含的项。而且,尽管在典型的文档中找到了关于这个主题的单词,但几乎没有人会将__repr_对象设置为eval可以用来构建相等对象的字符串(这太难了,而且不知道相关模块是如何实际导入的,这实际上是不可能的)。

因此,我的建议是:专注于使__str__合理地具有可读性,并尽可能地明确__repr___,即使这会干扰模糊的不可实现的目标,即使__repr_的返回值可接受作为__eval___的输入!

基本上__str__或str()用于创建人类可读的输出,这些输出必须面向最终用户。另一方面,repr()或__repr_主要返回对象的规范字符串表示,用于调试和开发,帮助程序员。

需要记住的一点是,容器的__str__使用包含的对象的__repr_。

>>> from datetime import datetime
>>> from decimal import Decimal
>>> print (Decimal('52'), datetime.now())
(Decimal('52'), datetime.datetime(2015, 11, 16, 10, 51, 26, 185000))
>>> str((Decimal('52'), datetime.now()))
"(Decimal('52'), datetime.datetime(2015, 11, 16, 10, 52, 22, 176000))"

Python比可读性更倾向于明确性,元组的__str__调用调用所包含对象的__repr_,即对象的“形式”表示。虽然正式表示比非正式表示更难理解,但它是明确的,并且对bug更为健壮。