防止在 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
并设置为字典。 d
是 A
的实现细节。 d
的所有访问都在 A
的代码中完成。只是 B
的 d
不应该与 A
的 d
.
相同
对于实例,我将在 __init__()
函数中创建该字典。但就我而言,我只使用 classes。
有没有一种标准的方法来实现这个(编辑:不改变子classes B
和C
的实现)?是否有类似于 __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
我在Python3中有以下情况:
class A:
d = {}
class B(A): pass
class C(A): pass
我只使用 classes,没有创建任何实例。当我访问 B.d
时,我将获得对 A.d
的共享引用。那不是我想要的。我想让每个继承 A
的 class 都有自己的 d
并设置为字典。 d
是 A
的实现细节。 d
的所有访问都在 A
的代码中完成。只是 B
的 d
不应该与 A
的 d
.
对于实例,我将在 __init__()
函数中创建该字典。但就我而言,我只使用 classes。
有没有一种标准的方法来实现这个(编辑:不改变子classes B
和C
的实现)?是否有类似于 __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