接上文,再介紹最后幾個常用的魔法方法。
?
關于__dict__:
先上個例子:
class Test(object):fly = Truedef __init__(self, age):self.age = age
?
__dict__魔法方法可以被稱為系統,他是存儲各分層屬性的魔法方法。__dict__中,鍵為屬性名,值為屬性本身。可以這樣理解,在平時我們給類和實例定義的那些屬性,都會被存儲到__dict__方法中用于讀取。而我們平時使用的類似這樣的語法Test.fly 其實就是調用了類屬性,同樣可以寫成Test.__dict__['fly']。除了類屬性,還有實例屬性。當我們用類實例化一個實例,例如上文我們使用p = Test(2)實例化類Test,p也會具有__dict__屬性。這里會輸出:
?
{'age': 2}
?
由上可以發現,python中的屬性是進行分層定義的。/object/Test/p這樣一層一層下來的。當我們需要調用某個屬性的時候,python會一層一層往上面遍歷上去。先從實例,然后實例的__class__的__dict__,然后是該類的__base__。這樣__dict__一路找上去。如果最后都沒有找到,就拋出AttributeError錯誤。
這里可以延伸一下,沒記錯的話,我前面有篇文章講了一個方法__slot__。__slots__方法就是通過限制__dict__,只讓類實例初始化__slots__里面定義的屬性,而且讓實例不再擁有__dict__方法,來達到節約內存的目的。我將會就上面的那個例子重寫一下,來說明這個問題。
?
class Test(object):__slots__ = ['age']fly = Truedef __init__(self, age):self.age = age
?
output:
In [25]: Test.__dict__ Out[25]: dict_proxy({'__doc__': None,'__init__': <function __main__.__init__>,'__module__': '__main__','__slots__': ['age'],'age': <member 'age' of 'Test' objects>,'fly': True})In [36]: p.__dict__ --------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-36-3a1cec47d020> in <module>() ----> 1 p.__dict__AttributeError: 'Test' object has no attribute '__dict__'In [37]: p.age Out[37]: 3In [38]: p.fly Out[38]: True
可以看到,__slots__方法并沒有阻止由下至上的屬性查找方法,只是不會再允許沒有包含在__slots__數組中的屬性再被賦值給實例了。但這并不妨礙,繼續調用允許訪問的屬性,以及類屬性。
?
關于__get__, __set__, __del__:
在前面的文章里面我也介紹過這三個魔法方法,雖然一般是用不到的,但是在寫庫的時候它們有特別的用途。他們是python另外一個協議descriptor的根基。
同一個對象的不同屬性之間可能存在依賴關系。當某個屬性被修改時,我們希望依賴于該屬性的其他屬性也同時變化。在這種環境下面__dict__方法就無法辦到。因為__dict__方法只能用來存儲靜態屬性。python提供了多種即時生成屬性的方法。其中一種就是property。property是特殊的屬性。比如我們為上面的例子增加一個property特性,使得他能夠動態變化。來看這個例子:
class Test(object):fly = Truedef __init__(self, age):self.age = agedef whether_fly(self):if self.age <= 30:return Trueelse:return Falsedef just_try_try(self, other):passwhether_fly = property(whether_fly)p = Test(20) print p.age print p.whether_fly p.age = 40 print p.age print p.whether_fly
output:
20 True 40 False
可以看到 我們可以使用這種手段,動態修改屬性值。property有四個參數。前三個參數為函數,分別用于處理查詢特性、修改特性、刪除特性。最后一個參數為特性的文檔,可以為一個字符串,起說明作用。這里我只是要到了第一個參數,查詢的時候動態修改他的返回值,而第二個參數是在修改值的時候就會體現出來。
?
Reference:
http://www.cnblogs.com/vamei/archive/2012/12/11/2772448.html
?