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


当前回答

__repr_在任何地方都使用,但print和str方法除外(当定义了__str__时!)

其他回答

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

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

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

我的经验法则是:__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___的输入!

__repr_:python对象的表示通常eval会将其转换回该对象

__str__:是你认为的文本形式的对象

e.g.

>>> s="""w'o"w"""
>>> repr(s)
'\'w\\\'o"w\''
>>> str(s)
'w\'o"w'
>>> eval(str(s))==s
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    w'o"w
       ^
SyntaxError: EOL while scanning single-quoted string
>>> eval(repr(s))==s
True

直观地理解和永久地区分它们。

__str__返回给定对象的字符串伪装体,以便于眼睛阅读__repr_返回给定对象的真实肉身(返回自身),以便明确识别。

在示例中看到

In [30]: str(datetime.datetime.now())
Out[30]: '2017-12-07 15:41:14.002752'
Disguised in string form

关于__代表__

In [32]: datetime.datetime.now()
Out[32]: datetime.datetime(2017, 12, 7, 15, 43, 27, 297769)
Presence in real body which allows to be manipulated directly.

我们可以方便地对__repr_结果进行算术运算。

In [33]: datetime.datetime.now()
Out[33]: datetime.datetime(2017, 12, 7, 15, 47, 9, 741521)
In [34]: datetime.datetime(2017, 12, 7, 15, 47, 9, 741521) - datetime.datetime(2
    ...: 017, 12, 7, 15, 43, 27, 297769)
Out[34]: datetime.timedelta(0, 222, 443752)

如果对__str应用操作__

In [35]: '2017-12-07 15:43:14.002752' - '2017-12-07 15:41:14.002752'
TypeError: unsupported operand type(s) for -: 'str' and 'str'

只返回错误。

另一个例子。

In [36]: str('string_body')
Out[36]: 'string_body' # in string form

In [37]: repr('real_body')
Out[37]: "'real_body'" #its real body hide inside

希望这能帮助你建立具体的基础来探索更多的答案。