一、屬性引用函式
hasattr(obj,name[,default])
getattr(obj,name)
setattr(obj,name,value)
delattr(obj,name)
二、屬性引用過載
def __setattr__(self,key,value):
1.攔截所有屬性的賦值語句。
2.self.attr=value 相當於 self.__setattr__("attr",value)。
3.如果在__setattr__中對任何self屬性賦值,都會再呼叫__setattr__,導致無窮遞迴迴圈。只能self.__dict__["attr"]=value 。
def __getattribute__(self, key):
1.攔截所有的屬性獲取,包括未定義的屬性,self.__dict__,等點號運算。
2.所有的屬性先在__getattribute__中沒有找到,就會丟擲AttributeError,__getattr__接收這個錯誤,此時進入__getattr__中繼續尋找。
3.如果__getattribute__沒有丟擲AttributeError,將不會呼叫__getattr__。
def __getattr__(self, key):
攔截self.attr運算。當在__dict__中未找到該屬性時,在類屬性中也沒有找到該屬性,並且在繼承樹中也沒有找到該屬性,就會呼叫這個方法。
def __delattr__(self,key): 刪除屬性
三、示例
class Square: # 正方形 def __init__(self, l): self.length = l # 邊長 def __getattr__(self, key): if key == "area": return "__getattr__被呼叫了,為了area" sq = Square(10) print(sq.length) # 10 print(sq.area) # __getattr__被呼叫了,為了area
class Square: # 正方形 def __init__(self, l): pass def __getattr__(self, key): print("__getattr__被呼叫了") if key == "length": return 1111 def __getattribute__(self, key123): print("__getattribute__被呼叫了") # return 123456 raise AttributeError sq = Square(10) print(sq.length) # __getattribute__被呼叫了 # __getattr__被呼叫了 # 1111
class Square: # 正方形 def __init__(self,l): pass def __getattr__(self, key): print("__getattr__被呼叫了") raise AttributeError("1111111") def __getattribute__(self, key123): print("__getattribute__被呼叫了") return 123456 # raise AttributeError sq = Square(10) print(sq.length) # __getattribute__被呼叫了 # 123456
class Square: # 正方形 def __init__(self, l): self.length = l # 邊長 def __setattr__(self, key, value): print("呼叫__setattr__", "key=", key) if key == "perimeter": self.__dict__["length"] = value / 4 self.__dict__["perimeter"] = value if key == "length": self.__dict__["length"] = value self.__dict__["perimeter"] = value * 4 def __getattr__(self, key): print("呼叫__getattr__ ,", "key =", key) if key == "area": return 960 def __getattribute__(self, key123): print("呼叫__getattribute__ ,", "key123 =", key123) return object.__getattribute__(self, key123) sq = Square(10) # 呼叫__setattr__ # 呼叫__getattribute__ , key123 = __dict__ 此時執行self.__dict__["length"] = value # 呼叫__getattribute__ , key123 = __dict__ 此時執行self.__dict__["perimeter"] = value * 4 print(sq.length) # 呼叫__getattribute__ , key123 = length 此時執行self.length = l # 邊長 print(sq.perimeter) # 呼叫__getattribute__ , key123 = perimeter # 40 print(sq.area) # 呼叫__getattribute__ , key123 = area # 呼叫__getattr__ , key = area # 960