Python如何重写__getattribute__实现类全方法调用日志且规避递归错误
递归错误原因
你遇到的递归问题核心原因是:在重写的__getattribute__内部,你又调用了当前类Classy的__getattribute__方法,这个调用本身会被你重写的拦截逻辑捕获,触发无限循环,最终栈溢出报错。
解决方案
把__getattribute__内部的调用逻辑改成调用父类的原生__getattribute__实现即可,Python所有类默认继承object类,用super()可以快速调用父类方法:
class Classy: def do_it(self): print('We did it!') def __getattribute__(self, attr): print(f'Calling {attr}') # 调用父类原生属性查找逻辑,不会触发当前类的重写拦截 return super().__getattribute__(attr) c = Classy() c.do_it()
运行后正常输出:
Calling do_it We did it!
相关疑问解答
- 调用父类的
__getattribute__能不能获取到子类的方法?
完全可以。Python原生的__getattribute__逻辑本身就会完整遍历当前实例对应类的继承链查找属性,不管是子类自定义的、还是从父类继承的属性/方法都能正常获取,你之前的写法是错误调用了当前类的重写方法才导致递归,换成父类原生实现没有这个问题。 - 为什么
__init__调用没有触发__getattribute__?
对于双下划线开头的魔术方法,Python解释器调用时会优先直接查找类对象的方法插槽,不会走实例级的__getattribute__拦截逻辑,所以实例初始化阶段的__init__调用不会被捕获。
内容的提问来源于stack exchange,提问作者ChaimG
相关产品推荐
相关产品推荐

