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


当前回答

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

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

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

其他回答

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

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

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

每个对象都从所有对象创建的基类继承__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__

其他答案中缺少的一个方面。的确,一般来说,模式是:

__str__的目标:人类可读__repr_的目标:明确,可能通过eval机器可读

不幸的是,这种区别是有缺陷的,因为Python REPL和IPython都使用__repr_在REPL控制台中打印对象(请参见Python和IPython的相关问题)。因此,以交互控制台工作为目标的项目(例如,Numpy或Pandas)已经开始忽略上述规则,转而提供一个人类可读的__repr_实现。

__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