object
類是全部類的父類,所以全部的類都有object類的屬性和方法。咱們顯然有必要深刻研究一下object類的結構。對於咱們深刻學習Python頗有好處。
其實咱們在前面第17講介紹繼承的時候,其實就已經介紹object
根類的一部分,包括使用mro()
函數查看類的繼承關係,此次咱們從另外角度來講明object
根類。python
仍是經過一個例子開始:git
class Person: count = 0 def __init__(self, name, age): self.name = name self.age = age def say_age(self): print("{0}的年齡是:{1}".format(self.name, self.age)) obj = object() print(dir(obj)) s = Person("聶發俊", 100) print(dir(s))
運行結果:github
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__'] ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'count', 'name', 'say_age']
程序說明:
這段程序已經很熟悉了,運行原理就不過多贅述了。咱們對比一下對象obj
和對象s
所返回的屬性列表,發現相比增長了一下幾個屬性:__dir__
, __module__
,__weakref__
,age
,count
,name
,say_age
。首先說簡單的:markdown
name
,age
count
say_age
__dir__
屬性列表只有存在類方法(靜態方法)、類屬性、實例屬性、實例方法中至少一項,纔會有__dict__
屬性。如上面例子中的對象obj
,就沒有__dict__
屬性。ssh
__module__
模塊屬性表明當前對象運行的模塊ide
class Person: pass p = Person() print(p.__module__)
運行結果:函數
__main__
程序說明:默認運行在__main__
模塊下。學習
__weakref__
弱引用屬性提及弱引用,就不得不說前面提到的Python垃圾回收機制,垃圾回收機制最核心的機制就是引用計數。weakref
的弱引用是相對於引用計數而言的,引用計數的方式也能夠叫作常規引用或者強引用(後面我的定義,若是不對,請多多指教。)
相同點: 不管是常規引用仍是弱引用,都可以經過引用的方式獲取到被引用對象的地址,換句話說,就是能夠具備被引用對象的想用的操做
區別:常規引用會增長引用計數,可是弱引用不會增長引用對象this
默認狀況下是沒有弱引用的:code
class Person: pass p = Person() print(p.__weakref__)
運行結果:
None
程序說明:普通對象在默認狀況下是不存在弱引用的。
下面咱們就介紹一下弱引用常見的兩種形式
weakref.ref(p_object)
方法使用weakref.ref
方法是最常規的方法,返回的是一個weakref
類型對象,若是須要只用引用,須要經過()
才能獲取到被引用對象。
示例代碼:
import weakref import sys class Person: def __init__(self, name, age): self.name = name self.age = age def ref_callback(reference): print("ref_callback") print(reference, "this weak reference invalid") p1 = Person("聶發俊", 100) print(sys.getrefcount(p1)) # 使用weakref.ref方法構建弱引用 wek1 = weakref.ref(p1, ref_callback) print(sys.getrefcount(p1)) print("--" * 20) print(p1.__weakref__) print(wek1) print(wek1()) print("{0}的年齡是:{1}".format(wek1().name, wek1().age)) print('--' * 20) del p1 print(wek1)
運行結果:
2 2 ---------------------------------------- <weakref at 0x00000260D5978CC8; to 'Person' at 0x00000260BE779908> <weakref at 0x00000260D5978CC8; to 'Person' at 0x00000260BE779908> <__main__.Person object at 0x00000260BE779908> 聶發俊的年齡是:100 ---------------------------------------- ref_callback <weakref at 0x00000260D5978CC8; dead> this weak reference invalid <weakref at 0x00000260D5978CC8; dead>
程序說明:
__weakref__
也有值了,指向和wek1
同樣的地址。wek1
是一個weakref
類型的對象,只有使用wek1()
的方式,才能獲取被引用對象__main__.Person
,使用被引用對象的實例屬性,也須要帶上()
ref_callback
,同時wek1
的弱引用狀態變成dead
狀態。weakref.proxy(p_object, callback)
方法使用weakref.proxy
方法建立弱引用返回被引用對象,相似於a=b
操做,這個是和使用ref
函數不同的地方。
示例代碼:
import weakref import sys class Person: def __init__(self, name, age): self.name = name self.age = age def proxy_callback(reference): print("proxy_callback call") p1 = Person("聶發俊", 100) print(sys.getrefcount(p1)) # 使用weakref.proxy方法構建弱引用 wek2 = weakref.proxy(p1, proxy_callback) print(sys.getrefcount(p1)) print("--" * 20) print(p1) print(wek2) print("{0}的年齡是:{1}".format(wek2.name, wek2.age)) print('--' * 20) del p1 print(wek2)
運行結果:
2 2 ---------------------------------------- <__main__.Person object at 0x0000010E9784F388> <__main__.Person object at 0x0000010E9784F388> 聶發俊的年齡是:100 ---------------------------------------- proxy_callback call Traceback (most recent call last): File "test.py", line 30, in <module> print(wek2) ReferenceError: weakly-referenced object no longer exists
程序說明:
weakref.proxy
返回的被引用對象,p1
和wek2
指向相同的地址0x000001EFF7219908
,使用實例屬性不須要()
p1
,方法weakref.proxy
指定的回調函數proxy_callback
會被調用,注意由於被引用對象先被刪除,而後在執行回調函數,這個時候雖然有參數reference代指被引用對象,可是不能使用,由於已經被刪除了 wek2
會提示錯誤信息,由於被引用對象p1
被刪除了,沒法獲取對象weakref.ref()
返回weakref
,使用被引用對象須要使用()
進行輔助,刪除被引用對象時,weakref
狀態變成dead
.weakref.proxy()
返回被引用對象,能夠直接使用被引用對象,刪除被引用對象時,proxy
不能再繼續使用,沒法再獲取被引用對象。備註:
更多精彩博客,請訪問: 聶發俊的技術博客
對應視頻教程,請訪問: python400
完整markdown筆記,請訪問: python400_learn_github