You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何__getattr__被调用而非捕获AttributeError?Python2.7方案咨询

这个问题其实是Python 2.7中属性查找机制的典型表现——当父类定义了__getattr__时,访问不存在的属性会优先调用这个方法,而不是抛出AttributeError,所以你的try-except块才没触发。下面有两种既保留Base的__getattr__又能维持try-except逻辑的解决方案:

方案1:在Derived类中重写__getattr__,针对特定属性抛出异常

这种方法能精确控制哪些属性需要触发AttributeError,其他属性仍然沿用父类的__getattr__行为:

class Base:
    def __init__(self):
        pass
    def __getattr__(self, item):
        print('__getattr__ was called!')

class Derived(Base):
    def __getattr__(self, item):
        # 当访问'val'且属性不存在时,直接抛出AttributeError
        if item == 'val':
            raise AttributeError("'Derived' object has no attribute '%s'" % item)
        # 其他属性交给父类的__getattr__处理
        return super(Derived, self).__getattr__(item)
    
    def GetValue(self):
        try:
            return self.val
        except AttributeError:
            self.val = 1
            return self.val

obj = Derived()
print(obj.GetValue())  # 输出1,不会触发Base的__getattr__
print(obj.non_existent)  # 触发Base的__getattr__,打印'__getattr__ was called!'

方案2:直接检查实例的__dict__

Python实例的属性会存储在__dict__字典中,我们可以通过检查这个字典来判断val是否已初始化,同时保留try-except块:

class Base:
    def __init__(self):
        pass
    def __getattr__(self, item):
        print('__getattr__ was called!')

class Derived(Base):
    def GetValue(self):
        try:
            # 先检查val是否在实例的属性字典中,不在则主动抛出异常
            if 'val' not in self.__dict__:
                raise AttributeError('val')
            return self.val
        except AttributeError:
            self.val = 1
            return self.val

obj = Derived()
print(obj.GetValue())  # 输出1

原理说明

  • 方案1通过重写__getattr__,对目标属性val直接抛出AttributeError,让try-except块能够捕获到,而其他属性仍正常触发父类的__getattr__。
  • 方案2利用了Python实例属性的存储机制:未初始化的val不会出现在self.__dict__中,此时主动抛出异常,确保except块执行初始化逻辑,同时不会触发父类的__getattr__。

内容的提问来源于stack exchange,提问作者Michal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:35:33