__getattr__(self, name) 定義當使用者試圖擷取一個不存在的屬性時的行為 : 當訪問對象的時name屬性時,若name屬性不存在,會自動調用__getattr__。如果存在,則不會調用__getattr__方法,而是直接返回name屬性
__getatribute__(self, name) 定義當該類的屬性被訪問時的行為 當訪問對象的name屬性時,無論name存不存在都會調用該方法
__setattr__(self, name, value) 定義當一個屬性被設定時的行為 當試圖給對象的name屬性進行賦值的時候調用
__delattr__(self, name) 定義當一個對象被刪除時的行為
上述四個方法中除了__getattr__以外,均可用help(object. )的方式查詢協助,但是__getattr__怎樣查詢還不太知道
只要重寫這四個魔法方法我們就可以控制對對象的屬性訪問了
這其中的三個方法和前面的getattr, setattr, delattr 是有區別的,一個由雙下劃,一個沒(愣了幾分鐘才反應過來,囧)
前面的參見:http://blog.csdn.net/sinat_41104353/article/details/79250415
>>> class C:def __getattribute__(self, name):print("getattribute")return super().__getattrbute__(name) #為了不影響原來__getattribute__功能的使用,故調用基類的__getattribute__def __getattr__(self, name):print("getattr") #這裡調用super().__getattr__(name)的話會報錯:AttributeError: 'super' object has no attribute '__getattr__'def __setattr__(self, name, value):print("setattr")super().__setattr__(name, value)def __delattr__(self, name):print("delattr")super().__delattr__(name)>>> c = C()>>> c.x #建立一個屬性xgetattribute #首先會調用__getattribue__方法getattr>>> c.x = 1setattr>>> c.xgetattribute1 #理論上應該是1,但是不知道為什麼這裡自己試的總是getattr>>> del c.xdelattr
注意:重寫這些方法容易造成死迴圈
看下例:
寫一個矩形類,預設有長和寬兩個屬性
如果為一個叫square的屬性賦值,那麼說明這是一個正方形,值就是正方形的邊長,此時間長度和寬都應該等於邊長。如果不是為其他名字的屬性賦值,則就是為該屬性賦值。
>>> class Rectangle:def __init__(self, width = 0, height = 0):self.width = width #發生賦值操作,就會觸發__setattr__方法self.height = heightdef __setattr__(self, name, value):if name == 'square':self.width = valueself.height = valueelse:self.name = value #又是一個賦值操作,觸發__setatrr__方法,造成死迴圈 解決方案(1)這裡改成調用基類的__setattr__方法,即super().__setattr__(name, value),一般推薦這一種 (2)改成self.__dict__[name] = valuedef getArea(self):return self.width * self.height>>> r = Rectangle(4, 5) #傳入參數調用__init__方法Traceback (most recent call last): File "<pyshell#55>", line 1, in <module> r = Rectangle(4, 5) File "<pyshell#54>", line 3, in __init__ self.width = width File "<pyshell#54>", line 10, in __setattr__ self.name = value File "<pyshell#54>", line 10, in __setattr__ self.name = value File "<pyshell#54>", line 10, in __setattr__ self.name = value [Previous line repeated 325 more times] File "<pyshell#54>", line 6, in __setattr__ if name == 'square':RecursionError: maximum recursion depth exceeded in comparison
>>> r = Rectangle(4, 5)>>> r.getArea()20>>> r.square = 10>>> r.width10>>> r.height10>>> r.getArea()100
當然,不只是有__setattr__方法會造成死迴圈,__getattribute__也會,避免方法見代碼注釋。