Python Every Class Needs a __repr__

1、思考

当咱们在Python中定义一个类的时候,若是咱们经过print打印这个类的实例化对象,或者咱们直接输入这个类实例化对象会返回怎么样的结果,以下代码:python

>>> class People(object):
...     def __init__(self, name, age):
...         self.name = name
...         self.age = age
...
>>> tom = People("Tom", 23)
>>> print(tom)
<__main__.People object at 0x00000000027A7160>
>>> tom
<__main__.People object at 0x00000000027A7160>
>>>

默认状况下,你获得的是一个字符串,其中包含类名和对象实例的id(这是CPython中对象的内存地址),其实有更加Pythonic的方式去控制不一样状况下将对象进行转换为字符串,也就是控制其显示的结果内容。 咱们把上面的代码进行更改的内容以下:程序员

>>> class People(object):
...     def __init__(self, name, age):
...         self.name = name
...         self.age = age
...     def __str__(self):
...         return f"people name is {self.name}"
...
>>> tom = People("Tom", 23)
>>> print(tom)
people name is Tom
>>> tom
<__main__.People object at 0x00000000021B7208>
>>>

str 是python的内置方法,而且当你在尝试去吧一个对象转换为一个字符串的时候怎么调用这个str方法,如咱们进行以下操做时:spa

>>> class People(object):
...     def __init__(self, name, age):
...         self.name = name
...         self.age = age
...     def __str__(self):
...         return f"people name is {self.name}"
...
>>> tom = People("Tom", 23)
>>> print(tom)
people name is Tom
>>> str(tom)
'people name is Tom'
>>> '{}'.format(tom)
'people name is Tom'
>>> tom
<__main__.People object at 0x00000000021E7208>
>>>

 

2、__str__ vs __repr__

在上面的代码中咱们添加了str_方法以后,当咱们将对象转换为字符串的时候都会调用str方法,并获得咱们本身定义的内容,可是并无影响到咱们在python交互模式下直接输入对象的返回内容。其实
repr 和 str 实际上是很是相似的,只不过用的场景不一样,将上面的代码进行调整:调试

>>> class People(object):
...     def __init__(self, name, age):
...         self.name = name
...         self.age = age
...     def __str__(self):
...         return f"people name is {self.name}"
...     def __repr__(self):
...         return f"__repr__: people name is {self.name}"
...
>>> tom = People("Tom", 23)
>>> print(tom)
people name is Tom
>>> str(tom)
'people name is Tom'
>>> '{}'.format(tom)
'people name is Tom'
>>> tom
__repr__: people name is Tom
>>>

 

其实这里也就验证了,在Python的交互模式下,检查一个对象,其实就是在调用对象的repr方法,还有一个你可能没有发现的地方就是当你在list,dict等容器中存储对象的时候,咱们打印看到的都是repr的内容,咱们把上面的tom存到列表里, 而后打印查看以下:code

>>> print([tom])
[__repr__: people name is Tom]
>>>

为了验证咱们到底应该怎么用这两个方法,毕竟这两个方法的做用仍是很是相似的,咱们能够经过Python标准库来验证一下,跟着标准库走总不会有错orm

>>> import datetime
>>> today = datetime.date.today()
>>> today
datetime.date(2019, 3, 5)
>>> str(today)
'2019-03-05'
>>> repr(today)
'datetime.date(2019, 3, 5)'
>>>

从这个Python标准库的用法,咱们也能很是好的理解str方法其实就是为了返回一我的们容易理解的字符串类型的结果,而repr方法更偏向于程序员方便去调试,能从结果中看到更加有用的信息,它甚至包括完整的模块和类对象

3、Why Every Class Needs a repr

咱们先看一下咱们将咱们上面代码的str方法去掉以后的结果:blog

>>> class People(object):
...     def __init__(self, name, age):
...         self.name = name
...         self.age = age
...     # def __str__(self):
...     #     return f"people name is {self.name}"
...     def __repr__(self):
...         return f"__repr__: people name is {self.name}"
...
>>> tom = People("Tom", 23)
>>> print(tom)
__repr__: people name is Tom
>>> str(tom)
'__repr__: people name is Tom'
>>> '{}'.format(tom)
'__repr__: people name is Tom'
>>> tom
__repr__: people name is Tom
>>>

从这里咱们发现当当你把对象进行字符串转换的时候,就会先去找str方法,若是没有则再去找repr方法执行
因此仍是建议在本身定义的类中都至少有一个repr方法,这样无论在上面状况下,你都能有一个对你来讲有用的字符串返回结果,而再也不是一个干巴巴的内存地址,因此在最后咱们规范一下咱们写一个Python类时的代码:内存

class People(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __str__(self):
        return f'people name is {self.name}'
    def __repr__(self):
        return (f'{self.__class__.__name__}('
                f'{self.name!r}, {self.age!r})')

在最后的repr的返回中咱们用了!r 这个意味着咱们要的repr(self.name) repr(self.age)而不是要str(self.name) str(self.age)的返回结果字符串

相关文章
相关标签/搜索