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('------->') #輸出結果 執行我啦 ------->