Python中__getattr__导致无法调用对象方法及递归报错问题求助
问题分析与解决方案
首先咱们拆解下你遇到的两个核心问题:
- 递归深度溢出:你在
__getattr__里调用getattr(self, "properties"),如果实例本身没有properties属性(比如没在__init__里初始化),会再次触发__getattr__来查找properties,无限循环导致递归报错。 - 无法调用方法:当调用对象方法时,方法属于类的成员,不在实例的
__dict__里,会触发__getattr__,但你的逻辑只返回properties里的属性,完全没处理方法的情况。
修正后的代码示例
class ParentClass(): def __init__(self): # 初始化自定义属性存储,这里用字典示例,后续可替换为你说的"values"结构 self.properties = {"name": "test_obj", "age": 25} def __getattr__(self, prop): # 直接从对象底层获取properties,绕过__getattr__,避免递归 try: props = object.__getattribute__(self, "properties") except AttributeError: raise AttributeError(f"'{self.__class__.__name__}' has no attribute '{prop}'") # 优先处理类定义的方法 class_method = getattr(self.__class__, prop, None) if class_method is not None and callable(class_method): return class_method # 处理自定义properties里的属性 if prop in props: value = props[prop] # 如果properties里存的是方法,需要绑定到当前实例才能正常调用 if callable(value): import types return types.MethodType(value, self) return value # 都找不到时抛出标准AttributeError,符合Python默认行为 raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{prop}'") class SubClass(ParentClass): def say_hello(self): print(f"Hello! I'm {self.name}, {self.age} years old.")
关键逻辑说明
- 避免递归:用
object.__getattribute__(self, "properties")直接从对象的属性底层获取值,不会触发__getattr__,彻底解决递归问题。 - 支持方法调用:先检查类中定义的方法(比如
SubClass里的say_hello),如果是可调用的方法就返回,这样调用obj.say_hello()就能正常执行。 - 动态方法支持:如果你的
properties里也存了自定义方法,会自动把方法绑定到当前实例,保证调用时能拿到self参数。
测试验证
obj = SubClass() print(obj.name) # 输出: test_obj obj.say_hello() # 输出: Hello! I'm test_obj, 25 years old. # 测试properties里的动态方法 obj.properties["greet"] = lambda self: print(f"Hi from {self.name}!") obj.greet() # 输出: Hi from test_obj!
内容的提问来源于stack exchange,提问作者CBusBus
相关产品推荐
相关产品推荐

