关于python:__str__和__repr__的目的是什么?

What is the purpose of __str__ and __repr__?

我真的不明白在Python中使用的__str____repr__在哪里。我的意思是,我得到__str__返回一个对象的字符串表示。但我为什么需要那个?在什么用例场景中?另外,我读到了__repr__的用法。

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


__repr__

Called by the repr() built-in function and by string conversions (reverse quotes) to compute the"official" string representation of an object. If at all possible, this should look like a valid Python expression that could be used to recreate an object with the same value (given an appropriate environment).

__str__

Called by the str() built-in function and by the print statement to compute the"informal" string representation of an object.

如果您有一个类,那么使用__str__,当您使用这个对象作为字符串的一部分时,您将需要一个信息性/非正式的输出。例如,可以为django模型定义__str__方法,然后在django管理界面中呈现这些方法。而不是像这样的东西,你会得到一个人的名字和姓氏,事件的名称和日期等。

__repr____str__是相似的,实际上有时是相等的(例如来自标准库sets.pyBaseSet类):

1
2
3
4
5
6
7
8
9
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__


一个你经常使用它们的地方是在一个互动会话中。如果打印一个对象,则会调用它的__str__方法,而如果只单独使用一个对象,则会显示它的__repr__

1
2
3
4
5
6
>>> 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__,返回相同的值(当然对于内置类型)也不常见。


蚱蜢,当有疑问的时候,去山上读古文。在它们中,您会发现uu repr_uu()应该:

If at all possible, this should look like a valid Python expression that could be used to recreate an object with the same value.


在前面的答案基础上建立和展示更多的例子。如果使用得当,strrepr之间的差别是明显的。简而言之,repr应该返回一个可以复制粘贴以重建对象的确切状态的字符串,而str对于loggingobserving调试结果很有用。下面是一些示例,以查看某些已知库的不同输出。

日期时间

1
2
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

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

麻木的

1
2
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示例

1
2
3
4
5
6
7
8
9
10
11
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作为调试输出更有用。

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

One thing to keep in mind, if str isn't defined but repr, str will automatically call repr. So, it's always good to at least define repr


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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

让我们有一个没有__str__函数的类。

1
2
3
4
5
6
7
8
9
10
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时,我们得到的是:

1
<__main__.Employee object at 0x7ff6fc0a0e48>

这不是很有帮助,当然,如果我们使用它来显示(如HTML),这不是我们想要打印的内容。

所以现在,同一个类,但是使用__str__函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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