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)的返回結果字符串

相關文章
相關標籤/搜索