二. __getattribute__


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


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM