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


当前回答

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

__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

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

其他回答

每个对象都从所有对象创建的基类继承__repr_。

class Person:
     pass

p=Person()

如果你调用repr(p),你会得到默认值:

 <__main__.Person object at 0x7fb2604f03a0>

但如果调用str(p),则会得到相同的输出。这是因为当__str__不存在时,Python调用__repr__

让我们实现自己的__str__

class Person:
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def __repr__(self):
        print("__repr__ called")
        return f"Person(name='{self.name}',age={self.age})"

p=Person("ali",20)

print(p)和str(p)将返回

 __repr__ called
     Person(name='ali',age=20)

让我们添加__str__()

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        
    def __repr__(self):
        print('__repr__ called')
        return f"Person(name='{self.name}, age=self.age')"
    
    def __str__(self):
        print('__str__ called')
        return self.name

p=Person("ali",20)

如果我们调用print(p)和str(p),它将调用__str__(),因此它将返回

__str__ called
ali

repr(p)将返回

repr调用“人(name=‘ali,age=self.age’)”

让我们省略__repr_,只实现__str__。

class Person:
def __init__(self, name, age):
    self.name = name
    self.age = age

def __str__(self):
    print('__str__ called')
    return self.name

p=Person('ali',20)

print(p)将查找__str__并返回:

__str__ called
ali

注意:如果我们定义了__repr_和__str__,则f'name为{p}'将调用__str__

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'

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

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

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

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

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

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

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