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


当前回答

优秀的答案已经涵盖了__str__和__repr_之间的差异,对我来说,这归结为前者即使是最终用户也可以阅读,后者对开发人员尽可能有用。考虑到这一点,我发现__repr_的默认实现常常无法实现这一目标,因为它忽略了对开发人员有用的信息。

出于这个原因,如果我有一个足够简单的__str__,我通常只会尝试通过以下方式来达到两全其美:

def __repr__(self):
    return '{0} ({1})'.format(object.__repr__(self), str(self))

其他回答

简而言之:

class Demo:
  def __repr__(self):
    return 'repr'
  def __str__(self):
    return 'str'

demo = Demo()
print(demo) # use __str__, output 'str' to stdout

s = str(demo) # __str__ is used, return 'str'
r = repr(demo) # __repr__ is used, return 'repr'

import logging
logger = logging.getLogger(logging.INFO)
logger.info(demo) # use __str__, output 'str' to stdout

from pprint import pprint, pformat
pprint(demo) # use __repr__, output 'repr' to stdout
result = pformat(demo) # use __repr__, result is string which value is 'str'

需要记住的一点是,容器的__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更为健壮。

Hans Petter Langtanch的《Python脚本用于计算科学》一书第358页明确指出

__repr_的目标是对象的完整字符串表示;__str__是返回一个用于打印的字符串。

所以,我更愿意把他们理解为

repr=再现str=字符串(表示)

从用户的角度来看尽管这是我在学习python时产生的误解。

同一页还提供了一个小但很好的示例,如下所示:

实例

In [38]: str('s')
Out[38]: 's'

In [39]: repr('s')
Out[39]: "'s'"

In [40]: eval(str('s'))
Traceback (most recent call last):

  File "<ipython-input-40-abd46c0c43e7>", line 1, in <module>
    eval(str('s'))

  File "<string>", line 1, in <module>

NameError: name 's' is not defined


In [41]: eval(repr('s'))
Out[41]: 's'

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

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

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

来自effbot的(非官方)Python参考Wiki(存档副本):

__str__“计算对象的“非正式”字符串表示。这与__repr_不同,因为它不必是有效的Python表达式:可以使用更方便或更简洁的表示。”