假设我们有一个包含一些类变量的基类 x x2 y y2
1 1 1 11 121
2 2 4 12 144
3 3 9 13 169
。此类还具有一个类方法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__
继承的变量,如果不存在,那么它们在哪里?
这不是Accessing class attributes from parents in instance methods的副本,因为我不只是想查询恰好在基类中的特定变量-我想列出它们却不知道他们的名字。这个问题中与MRO相关的答案可能也适用于此,但我认为原始问题有所不同。
答案 0 :(得分:0)
我用metaclass解决了这个问题,用它重新定义了派生类的创建方式。在这种方法中,我们感兴趣的所有类变量都会从基类复制到派生变量:
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__
,是否应出于某种原因避免这种情况。