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

Python包装类如何覆盖属性,使被包装类方法使用该属性?

问题与解决方案

问题描述

定义类A,包含@property装饰的prop属性,以及依赖该属性的method方法和other_prop属性:

class A:
    @property
    def prop(self) -> int:
        return 1

    @property
    def other_prop(self) -> int:
        return self.prop * 4  # 依赖self.prop

    def method(self) -> int:
        return self.prop * 2  # 依赖self.prop

随后定义包装类B,接收A的实例,重写prop属性,并通过__getattr__将未定义的属性委托给A:

class B:
    def __init__(self, a: A):
        self._a = a

    @property
    def prop(self) -> int:
        return 2  # 重写A的prop属性

    def __getattr__(self, attr):
        return getattr(self._a, attr)  # 委托未定义的属性给A实例

实际调用时出现不符合预期的结果:

  • 调用b.method()期望得到4(使用B的prop计算),但实际返回2(因为A的method中self指向原A实例,使用A的prop)
  • 访问b.other_prop期望得到8,实际返回4,原因同上

需求限制:

  • 不能使用继承
  • 不想在B中复制A的method或other_prop的逻辑
  • 尝试过__getattribute__但无效

解决方案

核心问题是:从A实例获取的方法/属性,其内部的self仍指向原A实例,而非B实例。我们需要在委托时,将这些可调用对象的self参数替换为B实例。

修改B类的__getattr__方法,针对方法和property做包装处理:

import functools

class A:
    @property
    def prop(self) -> int:
        return 1

    @property
    def other_prop(self) -> int:
        return self.prop * 4

    def method(self) -> int:
        return self.prop * 2

class B:
    def __init__(self, a: A):
        self._a = a

    @property
    def prop(self) -> int:
        return 2

    def __getattr__(self, attr):
        attr_obj = getattr(self._a, attr)
        
        # 处理方法:将方法绑定到B实例作为self参数
        if callable(attr_obj):
            return functools.partial(attr_obj, self)
        
        # 处理property:调用其getter时传入B实例
        elif isinstance(attr_obj, property):
            return attr_obj.fget(self)
        
        # 其他普通属性直接返回
        return attr_obj

原理说明

  1. 方法处理:使用functools.partial将A的方法与B实例绑定,调用方法时,self参数自动替换为B实例,方法内部的self.prop会访问B的prop属性。
  2. Property处理:直接调用A中property的fget方法,并传入B实例作为self,让property的计算逻辑使用B的prop属性。

测试验证:

a = A()
b = B(a)
print(b.method())       # 输出4,符合预期
print(b.other_prop)     # 输出8,符合预期

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 08:55:12