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

如何在Python中避免子类与基类共享类变量

解决方案:利用__init_subclass__(Python 3.6+)或元类

这问题太典型了!正好Python 3.6引入了__init_subclass__方法——它就是你要找的、在子类派生时自动调用的类级“初始化”钩子,完全满足你的所有要求:不用修改子类代码,所有逻辑都封装在父类A里,每个子类会拥有独立的d字典。

方法一:推荐用__init_subclass__(现代Python首选)

直接在父类A中定义这个方法,每当有子类继承A时,这个方法就会被调用,我们可以在这里为子类初始化独立的d:

class A:
    # 父类自身的d,子类不会共享这个,因为__init_subclass__会给子类创建新的
    d = {}

    def __init_subclass__(cls, **kwargs):
        # 调用父类的__init_subclass__(如果有的话)
        super().__init_subclass__(**kwargs)
        # 给当前子类创建独立的空字典
        cls.d = {}
        # 如果你需要让子类继承父类d的初始内容,可以改成:cls.d = cls.d.copy()

class B(A):
    pass

class C(A):
    pass

验证一下效果:

B.d['test'] = 'hello'
print(B.d)  # 输出 {'test': 'hello'}
print(C.d)  # 输出 {},完全独立,不受B的修改影响

这个方法的优势是简洁、易读,是Python官方专门为类级别的子类初始化场景设计的特性,不需要复杂的元类操作。

方法二:元类(兼容Python 3.5及以下版本)

如果你需要支持更老的Python版本,可以用元类来实现。元类负责创建类对象,我们可以在元类的__new__方法中为每个新生成的子类添加独立的d:

class ADictMeta(type):
    def __new__(meta, name, bases, attrs):
        # 创建新的类对象
        new_class = super().__new__(meta, name, bases, attrs)
        # 给子类设置独立的d字典
        new_class.d = {}
        return new_class

class A(metaclass=ADictMeta):
    d = {}

class B(A):
    pass

class C(A):
    pass

这个方案的效果和上面完全一致,只是元类的写法相对繁琐一些,适合需要兼容旧版本的场景。

关键说明

  • 两种方案都保证了所有子类的d是独立的,且不需要修改B、C的任何代码
  • 所有对d的访问逻辑依然可以封装在A的代码里,完全符合你说的“d是A的实现细节”的要求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:56:39