二. __getattribute__
1. 先看看 : __getattr__
class Bar:
def __getattr__(self, item):
print("沒找到,觸發了我")
bb = Bar()
bb.name # 沒找到,觸發了我
2.__getattribute__
class Bar:
def __init__(self,name):
self.name = name
def __getattribute__(self, item):
print(f"無論找沒找到,都觸發了我-->{item}")
bb = Bar("shawn")
bb.name # 無論找沒找到,都觸發了我-->name
bb.age # 無論找沒找到,都觸發了我-->age
3.兩者同時存在
🍔兩者同時存在
class Bar:
def __init__(self,name):
self.name = name
def __getattr__(self, item):
print("沒找到,觸發了我")
def __getattribute__(self, item):
print(f"無論找沒找到,都觸發了我-->{item}")
bb = Bar("shawn")
bb.name # 無論找沒找到,都觸發了我-->name
bb.age # 無論找沒找到,都觸發了我-->age
🍔設置異常
class Bar:
def __init__(self,name):
self.name = name
def __getattr__(self, item):
print("沒找到,觸發了我")
def __getattribute__(self, item):
print(f"無論找沒找到,都觸發了我-->{item}")
raise AttributeError('讓小弟接管') # 設置異常,直接交給__getattr__
bb = Bar("shawn")
bb.name
'''
無論找沒找到,都觸發了我-->name
沒找到,觸發了我
'''
bb.age
'''
無論找沒找到,都觸發了我-->age
沒找到,觸發了我
'''
[對象] . [屬性]
的調用順序 : 先執行 __getattribute__--->去類的名稱空間找--->__getattr__(本質是去對象自己的名稱空間找)
[對象] . [屬性]
的查找順序 : 對象自己--->類--->父類--->父類
4.總結
__getattribute__
方法優先級比__getattr__
高
- 沒有重寫
__getattribute__
的情況下, 默認使用的是父類的__getattribute__
方法
- 只有在使用默認
__getattribute__
方法中找不到對應的屬性時,才會調用__getattr__
- 如果是對不存在的屬性做處理,盡量把邏輯寫在
__getattr__
方法中
- 如果非得重寫
__getattribute__
方法,需要注意兩點:
- 第一是避免.操作帶來的死循環
- 第二是不要遺忘父類的
__getattribute__
方法在子類中起的作用