__str__和__repr__的目的是什么?


82

我真的不明白Python的用途__str____repr__用途。我的意思是,我得到的__str__返回对象的字符串表示形式。但是我为什么需要那个?在什么用例情况下?另外,我读到有关__repr__

但是我不明白的是,我将在哪里使用它们?



4
对于任何来自Ruby的人,tl; dr是:__str__=to_s__repr__= inspect
Ajedi32

Answers:


86

__repr__

repr()内置函数和字符串转换(反引号)调用以计算对象的“正式”字符串表示形式。如果可能的话,这应该看起来像一个有效的Python表达式,可用于重新创建具有相同值的对象(在适当的环境下)。

__str__

str()内置函数和print语句调用以计算对象的“非正式”字符串表示形式。

__str__每当您将此类用作字符串的一部分时使用,如果您有一个类,并且想要提供信息/非正式的输出。例如,您可以定义__str__Django模型的方法,然后在Django管理界面中对其进行呈现。<Model object>您将得到一个人的名字和姓氏,事件的名称和日期等信息,而不是类似的信息。


__repr____str__是相似的,实际上有时等于(实施例从BaseSet类中sets.py从标准库):

def __repr__(self):
    """Return string representation of a set.

    This looks like 'Set([<list of elements>])'.
    """
    return self._repr()

# __str__ is the same as __repr__
__str__ = __repr__

1
谢谢!这正是我想要的!
丹尼尔(Daniel)2010年

当我运行代码并尝试理解它时,return return self._repr()的作用是说__repr __()恰好接受了一个参数。
2015年

所以,我可以__repr__代替__str__Django使用吗?
阿米特·特里帕蒂

60

经常使用它们的一个地方是互动会话。如果打印对象,则将__str__调用其方法,而如果仅使用对象,__repr__则显示该对象:

>>> from decimal import Decimal
>>> a = Decimal(1.25)
>>> print(a)
1.25                  <---- this is from __str__
>>> a
Decimal('1.25')       <---- this is from __repr__

__str__目的是尽可能使人可读,而的__repr__目的应该是可以用来重新创建对象的内容,尽管在这种情况下,它通常不是创建对象的确切方式。

两者__str____repr__返回相同的值(对于内置类型肯定是这样)也很常见。


感谢您的示例,让我对默认使用的位置有了更好的了解
JayRizzo

17

蝈蝈,在怀疑的时候去山上阅读古代典籍。在其中,您会发现__repr __()应该:

如果可能的话,这应该看起来像一个有效的Python表达式,可用于重新创建具有相同值的对象。


6
-1,因为这甚至都没有尝试回答实际问题,即用例是什么。
Scott Griffiths 2010年

4
@斯科特:你是对的。但是话又说回来,实际的问题表明,绝对没有尝试首先使用主要文档。提出一个问题,表明您已经尝试过自己回答它,但是对它的某些方面仍然有些困惑,这是一回事,而发布这样的问题则完全是另一回事。只需在他的主题行中输入一个新问题,即可表明前6个建议的SO线程中有5个会回答他的问题,但他不会被打扰。我没有完全给他一个答案,但是我非常想动。
彼得·罗威尔

1
实际上,他确实说过自己已经读过__repr__,官方文档并没有真正回答您为什么要使用它的问题,而仅仅因为在其他地方回答了一个问题,也就不是一个很好的理由。这样就可以回答了(如果您不认为这个问题值得回答,那么您通常就不会回谷歌了!)如果您认为这个问题不值得回答,那么您就无法回答,尽管在这种情况下,我同意它已经很好地涵盖了因此,链接到重复项将是一个适当的响应。
Scott Griffiths 2010年

实际上,您是不正确的。文档明确说明了为什么要使用它,例如:“这通常用于调试,因此,表示形式应具有丰富的信息且无歧义,这一点很重要。” 我已经看到太多的论坛(论坛)在“帮助吸血鬼”的压力下沉没,让我感到痛苦的是,它开始传承了。至于与其他显而易见的SO答案的链接,这是在您在“主题”行中键入时插入的建议机制的全部目的,但他选择忽略所有建议。QED和PDQ也是如此。
彼得·罗威尔

5
好吧,文档仍然没有说明如何使用它进行调试,但是我真的不打算对此进行争论。我们至少同意您的答案没有解决问题,所以我的-1对我来说仍然是合理的。如果问题写得不好/重复/琐碎,那么您可以帮助改善问题,链接到重复项或简单地对问题进行否决。我认为我的主要反对意见是答案应尝试回答问题-还有其他批评该问题的机制。我现在闭嘴,因为我认为我们俩在这里都有更好的事情要做。
Scott Griffiths

14

建立在先前的答案之上,并显示更多示例。如果使用正确,则str和之间的区别repr很明显。总之repr应返回的字符串,可以是复制粘贴到重建对象的确切状态,而str为有用loggingobserving调试的结果。以下是一些示例,以查看某些已知库的不同输出。

约会时间

print repr(datetime.now())    #datetime.datetime(2017, 12, 12, 18, 49, 27, 134411)
print str(datetime.now())     #2017-12-12 18:49:27.134452

可以将str其打印到日志文件中,repr如果要直接运行该日志文件或将其作为命令转储到文件中,可以将其重新用途。

x = datetime.datetime(2017, 12, 12, 18, 49, 27, 134411)

脾气暴躁的

print repr(np.array([1,2,3,4,5])) #array([1, 2, 3, 4, 5])
print str(np.array([1,2,3,4,5]))  #[1 2 3 4 5]

在Numpy中,它又repr可以直接消费。

自定义Vector3示例

class Vector3(object):
    def __init__(self, args):
        self.x = args[0]
        self.y = args[1]
        self.z = args[2]

    def __str__(self):
        return "x: {0}, y: {1}, z: {2}".format(self.x, self.y, self.z)

    def __repr__(self):
        return "Vector3([{0},{1},{2}])".format(self.x, self.y, self.z)

在此示例中,repr再次返回可以直接使用/执行的字符串,而str作为调试输出更为有用。

v = Vector3([1,2,3])
print str(v)     #x: 1, y: 2, z: 3
print repr(v)    #Vector3([1,2,3])

要记住的一件事是,如果str未定义reprstr则会自动调用repr。因此,至少定义一个总是好的repr


5

让我们拥有一个没有__str__功能的类。

class Employee:

    def __init__(self, first, last, pay):
        self.first = first 
        self.last = last
        self.pay = pay

emp1 = Employee('Ivan', 'Smith', 90000)

print(emp1)

当我们打印类的实例时,emp1我们得到的是:

<__main__.Employee object at 0x7ff6fc0a0e48>

这不是很有帮助,并且如果我们使用它来显示(例如在html中),当然这不是我们想要打印的内容

所以现在,同一个类,但是具有__str__功能:

class Employee:

    def __init__(self, first, last, pay):
        self.first = first 
        self.last = last
        self.pay = pay

    def __str__(self):
        return(f"The employee {self.first} {self.last} earns {self.pay}.")
        # you can edit this and use any attributes of the class

emp2 = Employee('John', 'Williams', 90000)

print(emp2)

现在,不用打印一个对象,而是使用__str__函数的返回值获取指定的内容:

The employee John Williams earns 90000


3

str将是非正式且可读的格式,而repr将提供正式的对象表示。

class Complex:
    # Constructor
    def __init__(self, real, imag):
        self.real = real
        self.imag = imag

    # "official" string representation of an object
    def __repr__(self):
        return 'Rational(%s, %s)' % (self.real, self.imag)

    # "informal" string representation of an object (readable)
    def __str__(self):
        return '%s + i%s' % (self.real, self.imag)

    t = Complex(10, 20)

    print (t)     # this is usual way we print the object
    print (str(t))  # this is str representation of object 
    print (repr(t))  # this is repr representation of object   

Answers : 

Rational(10, 20) # usual representation
10 + i20      # str representation
Rational(10, 20)  # repr representation

1

strrepr都是表示的方式。您可以在编写课程时使用它们。

class Fraction:
def __init__(self, n, d):
    self.n = n
    self.d = d
def __repr__(self):
    return "{}/{}".format(self.n, self.d)

例如,当我打印它的实例时,它返回东西。

print(Fraction(1, 2))

结果是

1/2

class Fraction:
def __init__(self, n, d):
    self.n = n
    self.d = d
def __str__(self):
    return "{}/{}".format(self.n, self.d)
print(Fraction(1, 2))

也导致

1/2

但是,如果您同时编写了两者,那么python使用哪个呢?

class Fraction:
def __init__(self, n, d):
    self.n = n
    self.d = d
def __str__(self):
    return "str"
def __repr__(self):
    return "repr"

print(Fraction(None, None))

这导致

str

因此,当两者都编写时,python实际上使用str方法而不是repr方法。


这样行吗?
KingWitherBrine
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.