二. __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__
方法在子类中起的作用