1. 程式人生 > >python學習日記(OOP——類的內建方法)

python學習日記(OOP——類的內建方法)

__str__和__repr__

改變物件的字串顯示__str__,__repr__

我們先定義一個Student類,列印一個例項:

class Student(object):
    def __init__(self,name):
        self.name = name

print(Student('libai'))

打印出一堆<__main__.Student object at 0x000002311102EE10>,不好看。

怎麼才能列印得好看呢?只需要定義好__str__()方法,返回一個好看的字串就可以了:

class Student(object):
    
def __init__(self,name): self.name = name def __str__(self): return 'Student object(name:%s)'%self.name print(Student('libai'))

這樣打印出來的例項,不但好看,而且容易看出例項內部重要的資料。

但是細心的朋友會發現直接敲變數不用print(在互動式直譯器下,打印出來的例項還是不好看:

 

這是因為直接顯示變數呼叫的不是__str__(),而是__repr__(),兩者的區別是__str__()

返回使用者看到的字串,而__repr__()返回程式開發者看到的字串,也就是說,__repr__()是為除錯服務的。

解決辦法是再定義一個__repr__()。但是通常__str__()__repr__()程式碼都是一樣的,所以,有個偷懶的寫法:

class Student(object):
    def __init__(self,name):
        self.name = name
    def __str__(self):
        return 'Student object(name:%s)'%self.name
    __repr__ = __str__
print(Student('libai'))
'''
str函式或者print函式--->obj.__str__()
repr或者互動式直譯器--->obj.__repr__()
如果__str__沒有被定義,那麼就會使用__repr__來代替輸出
注意:這倆方法的返回值必須是字串,否則丟擲異常
'''

__call__

一個物件例項可以有自己的屬性和方法,當我們呼叫例項方法時,我們用instance.method()來呼叫。能不能直接在例項本身上呼叫呢?在Python中,答案是肯定的。

任何類,只需要定義一個__call__()方法,就可以直接對例項進行呼叫。請看示例:

class Student(object):
    def __init__(self,name):
        self.name = name

    def __call__(self):
        print('My name is %s'%self.name)

s = Student('libai')
s()

__call__()還可以定義引數。對例項進行直接呼叫就好比對一個函式進行呼叫一樣,所以你完全可以把物件看成函式,把函式看成物件,因為這兩者之間本來就沒啥根本的區別。

如果你把物件看成函式,那麼函式本身其實也可以在執行期動態創建出來,因為類的例項都是執行期創建出來的,這麼一來,我們就模糊了物件和函式的界限。

那麼,怎麼判斷一個變數是物件還是函式呢?其實,更多的時候,我們需要判斷一個物件是否能被呼叫,能被呼叫的物件就是一個Callable物件,比如函式和我們上面定義的帶有__call__()的類例項:

print(callable(Student))
print(callable(len))
print(callable('123'))

通過callable()函式,我們就可以判斷一個物件是否是“可呼叫”物件。

__len__

class A:
    def __init__(self):
        self.a = 1
        self.b = 2

    def __len__(self):
        return len(self.__dict__)
    #不定義這個方法,異常是:object of type 'A' has no len()
a = A()
print(len(a))

__del__

僅瞭解。

析構方法,當物件在記憶體中被釋放時,自動觸發執行。

注:此方法一般無須定義,因為Python是一門高階語言,程式設計師在使用時無需關心記憶體的分配和釋放,因為此工作都是交給Python直譯器來執行,所以,解構函式的呼叫是由直譯器在進行垃圾回收時自動觸發執行的。

class Foo:

    def __del__(self):
        print('執行我啦')

f1=Foo()
del f1
print('------->')

#輸出結果
執行我啦
------->