防止在 Python 中与基数 class 共享 class 变量

Prevent sharing of class variables with base class in Python

我在Python3中有以下情况:

class A:
    d = {}

class B(A):  pass
class C(A):  pass

我只使用 classes,没有创建任何实例。当我访问 B.d 时,我将获得对 A.d 的共享引用。那不是我想要的。我想让每个继承 A 的 class 都有自己的 d 并设置为字典。 dA 的实现细节。 d 的所有访问都在 A 的代码中完成。只是 Bd 不应该与 Ad.

相同

对于实例,我将在 __init__() 函数中创建该字典。但就我而言,我只使用 classes。

有没有一种标准的方法来实现这个(编辑:不改变子classes BC的实现)?是否有类似于 __init__() 的东西在派生时被要求(或在)每个派生的 class?

简单测试@meissner_评论:您可以轻松地将子类中的 d 替换为其他子类。

class BaseA():
    """Provides basic initialization for dicts used in A() and deriveds."""
    @classmethod
    def InitDefaults(cls):
        return { 1: "this", 2:"are", 3:"some", 4:"defaults"}

class A():
    d = BaseA.InitDefaults()

class B(A):
    d = BaseA.InitDefaults()

class C(A):
    d = BaseA.InitDefaults()


print(A.d)
print(B.d)
print(C.d)

print("\n")
B.d[99] = "Not a default"
C.d[42] = "Not THE answer"

print(A.d)
print(B.d)
print(C.d)

输出:

{1: 'this', 2: 'are', 3: 'some', 4: 'defaults'}
{1: 'this', 2: 'are', 3: 'some', 4: 'defaults'}
{1: 'this', 2: 'are', 3: 'some', 4: 'defaults'}


{1: 'this', 2: 'are', 3: 'some', 4: 'defaults'}
{1: 'this', 2: 'are', 3: 'some', 4: 'defaults', 99: 'Not a default'}
{1: 'this', 2: 'are', 3: 'some', 4: 'defaults', 42: 'Not THE answer'}

这有点难看,但可以用。你有一个代码修改 "base-default" 的中心位置,A、B、C 得到不同的指令 - 初始化相同 - 可以向不同的方向发展。

可能更好的方法是使用实​​例和 init() 虽然 ...

我自己使用元类找到了解决方案:

class M(type):
  def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.d = {}

class A(metaclass=M): pass

然后可以创建 A 的子类,它们都有自己的 d 属性:

class B(A): pass

B.d is A.d
False