__repr__ 和 eval() 之间的关系是什么,__repr__ 的主要目的是什么?

3
我刚看到这个问题Python中__str____repr__的区别,其中提到__repr__的主要目的是不含歧义。但我听说__repr__的主要目的是生成一个字符串,以便之后eval()可以重构Python对象。实际上,__repr__的主要目的是什么?Python内置函数或默认模块是否本质上使用__repr__来重构对象?如果我们只覆盖__repr__使其始终返回常量字符串(例如“foo”),是否会破坏执行?
2个回答

9
对于具有字面符号表示法(例如strintfloatlist等)的类型,repr()会返回一个字符串,该字符串可用于再次创建该类型。
这很好,但不是必需的。 __repr__的主要目的是为了为开发人员提供关于所拥有对象的明确信息,以便进行调试。
引用自__repr__文档
“由内置函数repr()调用,以计算对象的'官方'字符串表示形式。如果可能的话,它应该看起来像一个有效的Python表达式,可以在具有相同值的情况下重新创建对象(在适当的环境中)。如果不可能,应返回形式如<...some useful description...>的字符串。”
但最重要的是:
“这通常用于调试,因此表示形式应丰富而明确。”
重点突出。
从您的自定义类型返回常量字符串在技术上不会破坏任何内容,但会使您作为开发人员的生活更加困难。

4
+1,__str__() 是为了用户设计的,而 __repr__() 则是为了开发者设计的。 - Gareth Latty
这个答案根本没有解释__repr__eval之间的关系,而这似乎是问题所在。如果你在不覆盖__repr__的情况下使用eval,你可能会得到SyntaxError: invalid syntax错误,就像我现在遇到的一样。实际上,eval需要一个表达式,如果你某个类的对象不能转换为表达式,那么你就会得到这个语法错误。这就是为什么__repr__也是必需的,因此它不仅仅用于调试目的。 - nbro
@nbro:这个问题询问__repr__的目的是什么。没有其他关系,如果类型返回一个与创建对象语法匹配的字符串,则将其传递给eval()将起作用,但这不是一个具体的要求。 - Martijn Pieters

2
惯例上,您使用 repr 来获取代表对象的字符串,使用 str 来描述它。 repr 更多用于调试,str 用于常规打印。这样做的想法是 repr 的输出看起来像您可以 eval 的代码,并且通常确实是这样。但是,您不能依赖此功能。如果您必须将对象转换为字符串并返回,请使用 picklejson

例如:
>>> greeting = "Hello"
>>> print str(greeting)
Hello

>>> print repr(greeting)
'Hello'

如果您正在编写自己的类,并且它非常简单,您可以使__repr__返回一些可被eval函数解析的内容:

class Song(object):
    def __init__(self, title, artist):
        self.title = title
        self.artist = artist

    def __repr__(self):
        return "Song(%r, %r)" % (self.title, self.artist)

    def __str__(self):
        return "%s - %s" % (self.artist, self.title)

请注意,我使用%r获取标题和艺术家的repr。这会自动处理转义和引用(对于Python),并允许我评估repr(a_song)的结果,尽管我在除了调试之外不会这样做。同样,str返回给用户打印的内容,repr则是帮助您调试的内容。如果该类比此更复杂,则无法从repr返回完整或可评估的内容。在这里的约定是返回一个简洁的字符串以标识您的实例,通常使用角括号:
>>> repr(type(None))
"<type 'NoneType'>"

>>> import gtk
>>> win = gtk.Window()
>>> repr(win)
'<gtk.Window object at 0x10de45690 (GtkWindow at 0x7fdd89240000)>'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接