Python subclass counter
我有这个python代码。结果是x的
基本上,我有一个class属性,它是一个计数器,它在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | class AttrDisplay: def gatherAttrs(self): attrs = [] for key in sorted(self.__dict__): attrs.append('%s=%s' % (key, getattr(self, key))) return ', '.join(attrs) def __repr__(self): return '[%s: %s]' % (self.__class__.__name__, self.gatherAttrs()) class TopTest(AttrDisplay): count = 0 def __init__(self): self.attr1 = TopTest.count self.attr2 = TopTest.count+1 TopTest.count += 2 class SubTest(TopTest): pass X, Y = TopTest(), SubTest() print(X) print(Y) |
您可以显式地访问和使用
要使子类具有自己的类变量,只需在其定义中添加一个
1 2 | class SubTest(TopTest): count = 0 |
你很接近——当你查找一个对象的属性时,你不一定要查找一个属于对象本身的属性。相反,查找遵循python的方法解析顺序,这…不是很简单。然而,在这种情况下,只执行三个步骤:
简单地说,当您访问
还有一个事实是,您的代码中有一个bug——子测试增加了
1 2 3 4 | def __init__(self): self.attr1 = self.__class__.count self.attr2 = self.__class__.count + 1 self.__class__.count += 2 |
这样,当您调用
您似乎希望为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | class TestMeta(type): def __new__(cls, name, bases, attrs): new_class = super().__new__(cls, name, bases, attrs) new_class.count = 0 return new_class class TopTest(AttrDisplay, metaclass=TestMeta): def __init__(self): self.attr1 = self.count self.attr2 = self.count + 1 self.increment_count(2) @classmethod def increment_count(cls, val): cls.count += val class SubTest(TopTest): pass |
你的
1 2 3 4 5 6 7 8 | >>> x, y = TopTest(), SubTest() >>> x.attr2 1 >>> y.attr2 1 >>> y2 = SubTest() >>> y2.attr2 3 |
然而,元类可能会令人困惑,只有在它们确实是必要的时候才应该使用。在您的特定情况下,只需为
1 2 | class SubTest(TopTest): count = 0 |
如果您希望每个类隐式地拥有它自己的类变量,那么可以使用元类来添加该变量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class MetaCount(type): def __new__(cls, name, bases, attrs): new_cls = super(MetaCount, cls).__new__(cls, name, bases, attrs) new_cls.count = 0 return new_cls class Parent(metaclass=MetaCount): def __init__(self): self.attr1 = self.count self.attr2 = self.count + 1 type(self).count += 2 # self.count += 2 creates an *instance* variable class Child(Parent): pass p, c = Parent(), Child() print(p.count) # 2 print(c.count) # 2 |
当创建
由于
这种行为可以通过重新定义
1 2 | class SubTest(TopTest): count = 0 |