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

如何为含__slots__的外部Python类实例添加额外数据?

解决带有__slots__的外部类实例添加额外数据的问题

你拥有一个不受控制的Python类A的实例a,对A的内部实现(包括__init__方法)完全不了解。由于A定义了__slots__,无法直接给a添加新属性,你希望找到办法让带有额外数据的对象能像A的实例一样正常工作,尝试通过子类化A实现包装类但不知道如何正确初始化父类。

以下是两种可行的解决思路:

方案一:组合+属性代理(推荐,无需依赖父类实现)

不用继承A,而是创建一个包装类持有原A实例的引用,通过__getattr__代理所有原实例的属性和方法。这样包装对象既能完全复用原实例的功能,又能自由添加额外属性。

class A:
    __slots__ = ["data"]
    def __init__(self, data):
        self.data = data

# 外部创建的原实例
a = A([1, 2, 3])

class Wrapper:
    def __init__(self, original_instance, extra_data):
        self._original = original_instance
        self.extra_data = extra_data
    
    # 代理原实例的所有属性和方法(访问不存在的属性时触发)
    def __getattr__(self, name):
        return getattr(self._original, name)
    
    # 支持修改原实例的属性(区分包装类自身属性和原实例属性)
    def __setattr__(self, name, value):
        if name in ["_original", "extra_data"]:
            super().__setattr__(name, value)
        else:
            setattr(self._original, name, value)

# 使用示例
w = Wrapper(a, [27])
print(w.data)        # 输出 [1, 2, 3],复用原实例属性
print(w.extra_data)  # 输出 [27],自定义额外属性
w.data.append(4)
print(a.data)        # 输出 [1, 2, 3, 4],原实例同步修改

如果原实例有__str__、__len__这类特殊方法,需要在包装类中手动代理,因为特殊方法会直接从类层面查找,不会触发__getattr__:

def __str__(self):
    return str(self._original)

def __len__(self):
    return len(self._original)

方案二:子类化+复制原实例状态(适合必须继承A的场景)

如果你的场景要求对象必须是A的子类实例,可以跳过调用父类__init__,直接复制原A实例的所有属性到子类实例中。注意子类不要定义__slots__,这样子类实例会自带__dict__,可以自由添加额外属性。

class A:
    __slots__ = ["data"]
    def __init__(self, data):
        self.data = data

a = A([1, 2, 3])

class Wrap(A):
    # 子类不定义__slots__,保留实例的__dict__用于添加自定义属性
    def __init__(self, original_instance, extra_data):
        # 遍历原实例的__slots__,复制所有属性到子类实例
        for slot in original_instance.__slots__:
            setattr(self, slot, getattr(original_instance, slot))
        self.extra_data = extra_data

# 使用示例
w = Wrap(a, [27])
print(w.data)        # 输出 [1, 2, 3]
print(w.extra_data)  # 输出 [27]
print(isinstance(w, A))  # 输出 True,确实是A的子类实例

如果原类A的__slots__包含继承来的属性,可以用dir(original_instance)过滤出实例属性后再复制。

内容的提问来源于stack exchange,提问作者Nico Schlömer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 22:45:27