访问派生类中继承类变量的dict



假设我们有一个基类A,它包含一些类变量。这个类还有一个类方法foo对这些变量执行一些操作。由于这种行为不应该被硬编码(例如,我们不希望在添加新的类变量时必须修改foo(,foo读取cls.__dict__,而不是直接引用变量
现在我们介绍一个派生类:B用更多的类变量扩展了A,并继承了foo。代码示例:

class A:
x = 0
y = 1
@classmethod
def foo(cls):
print([name for name, prop in cls.__dict__.items() if type(prop) is int])
class B(A):
z = 3
print(B.x)  # prints "0"
A.foo()     # prints "['x', 'y']"
B.foo()     # prints "['z']" -- why not "['x', 'y', 'z']"?

因此,我的问题是:为什么B.__dict__不包含从A继承的变量,如果不包含,那么它们在哪里?

这与在实例方法中从父类访问类属性不同,因为我不想查询基类中的特定变量,我想在不知道它们名称的情况下列出它们。这个问题中给出的与MRO相关的答案可能也适用于这里,但在我看来,最初的问题不同。

我用元类解决了这个问题,用它来重新定义派生类的创建方式。在这种方法中,我们感兴趣的所有类变量都从基类复制到派生类:

class M(type):
def __new__(cls, name, bases, dct):
for base in bases:
for name, prop in base.__dict__.items():
if type(prop) is int:
dct[name] = prop
return super(M, cls).__new__(cls, name, bases, dct)
class A(metaclass=M):
x = 0
y = 1
@classmethod
def foo(cls):
print([name for name, prop in cls.__dict__.items() if type(prop) is int])
class B(A):
z = 3
A.foo()  # prints "['y', 'x']"
B.foo()  # prints "['y', 'x', 'z']"

此外,元类的定义方式可以使foo甚至不必查询__dict__——如果出于某种原因必须避免,则可以将感兴趣的变量放入列表中,而不是修改__dict__

最新更新