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

Python重写属性时执行流程中断问题求助

重写属性时执行流程中断问题解析

问题场景

定义Chicken类:

class Chicken:
    
    def __init__(self):
        self._colour = "yellow"
    
    @property
    def colour(self):
        return self._colour

委托类ChickenDelegator:

class ChickenDelegator:
    
    def __init__(self, delegatee):
        self._delegatee = delegatee
        self._props = [ "colour" ]
    
    def get_delegatee(self):
        return self.__dict__["_delegatee"]

    def __getattr__(self, name):
        if name in self.__dict__["_props"]:
            return getattr(self.get_delegatee(), name)
        return super().__getattr__(name)
    
    def __setattr__(self, name, value):
        if "_props" in self.__dict__ and name in self.__dict__["_props"]:
            setattr(self.get_delegatee(), name, value)
        super().__setattr__(name, value)

子类Vulture:

class Vulture(ChickenDelegator):
    
    def __init__(self):
        super().__init__(Chicken())   

    @property
    def colour(self):
        print("Vulture colour property called")
        res = super().colour # 执行流程在此处中断!?
        #res = self.get_delegatee().colour # 此方式可行
        print("使用super().colour时不会执行到这一行!")
        res = f"brown and {res}"
        return res

测试场景:

if __name__ == "__main__":
    v = Vulture()
    print(f"Vulture is {v.colour}")
    # 预期输出: "Vulture is brown and yellow"
    # 实际输出: "Vulture is yellow"

在Vulture类的colour属性中,使用super().colour能返回正确值,但执行流程会在此处中断;而使用self.get_delegatee().colour时,不仅能返回正确值,执行流程还能继续,这是期望的行为。请问为何在此场景下使用super().property_name会导致执行流程中断?


相关评论翻译

在他的案例中,流程中断是因为手动抛出了异常。如果我把raise AttributeError(...)语句替换成return 100,执行流程会按预期从F返回到G再回到主程序。另外,在我的案例中__getattribute__的表现完全相同,而在他的案例中这解决了问题。


问题原因解析

你遇到的核心问题源于super()属性查找与__getattr__的交互逻辑,结合代码实际运行情况,流程中断的真实原因及逻辑如下:

  1. super()的属性查找逻辑
    当在Vulture的colour getter中调用super().colour时,super()代理的是父类ChickenDelegator,但ChickenDelegator本身没有定义colour类属性(如property),因此Python会触发当前实例(Vulture对象v)的__getattr__方法(继承自ChickenDelegator)。

  2. __getattr__的直接返回特性
    ChickenDelegator.__getattr__会直接返回委托对象Chicken实例的colour属性值(字符串"yellow"),而非一个可进一步处理的property对象。但理论上这并不会导致流程中断——Vulture的colour getter应该继续执行后续代码,将结果拼接为"brown and yellow"。

  3. 流程中断的真实诱因
    你观察到的"流程中断"大概率是因为Vulture的colour property根本没有被触发,常见原因包括:

    • Vulture的colour property存在缩进错误(比如被嵌套在__init__方法内部,成为局部函数而非类属性);
    • 代码运行环境的缓存或其他干扰,导致Vulture的类属性未被正确识别。

解决方案

  • 检查Vulture类中@property装饰的colour方法的缩进,确保它是类的直接成员,而非__init__的内部函数;
  • 优先使用self.get_delegatee().colour的方式,直接访问委托对象的属性,避免super()和__getattr__的复杂交互;
  • 若坚持使用super(),可在ChickenDelegator中显式定义colour property,替代__getattr__的委托逻辑:
    class ChickenDelegator:
        # ... 其他代码 ...
        @property
        def colour(self):
            return self.get_delegatee().colour
    
    这样super().colour会直接调用ChickenDelegator的colour property,返回委托对象的属性值,同时Vulture的colour getter后续代码会正常执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 01:52:33