【发布时间】:2018-02-24 12:46:07
【问题描述】:
试图理解 python 中的 oop 我遇到了这种让我困惑的情况,我无法找到令人满意的解释...... 我正在构建一个 Countable 类,它有一个计数器属性,用于计算已初始化的类实例的数量。我希望在初始化给定类的子类(或子子类)时也增加这个计数器。这是我的实现:
class Countable(object):
counter = 0
def __new__(cls, *args, **kwargs):
cls.increment_counter()
count(cls)
return object.__new__(cls, *args, **kwargs)
@classmethod
def increment_counter(cls):
cls.counter += 1
if cls.__base__ is not object:
cls.__base__.increment_counter()
count(cls) 在哪里用于调试目的,后来我把它写下来。
现在,让我们有一些它的子类:
class A(Countable):
def __init__(self, a='a'):
self.a = a
class B(Countable):
def __init__(self, b='b'):
self.b = b
class B2(B):
def __init__(self, b2='b2'):
self.b2 = b2
def count(cls):
print('@{:<5} Countables: {} As: {} Bs: {} B2s: {}'
''.format(cls.__name__, Countable.counter, A.counter, B.counter, B2.counter))
当我运行如下代码时:
a = A()
a = A()
a = A()
b = B()
b = B()
a = A()
b2 = B2()
b2 = B2()
我得到以下输出,这对我来说看起来很奇怪:
@A Countables: 1 As: 1 Bs: 1 B2s: 1
@A Countables: 2 As: 2 Bs: 2 B2s: 2
@A Countables: 3 As: 3 Bs: 3 B2s: 3
@B Countables: 4 As: 3 Bs: 4 B2s: 4
@B Countables: 5 As: 3 Bs: 5 B2s: 5
@A Countables: 6 As: 4 Bs: 5 B2s: 5
@B2 Countables: 7 As: 4 Bs: 6 B2s: 6
@B2 Countables: 8 As: 4 Bs: 7 B2s: 7
为什么一开始 A 和 B 的计数器都在递增,尽管我只调用了 A()?为什么在我第一次调用B() 之后它的行为就像预期的那样?
我已经发现要具有我想要的行为,在每个子类中添加 counter = 0 就足够了,但我无法找到解释为什么它会这样......谢谢!
我添加了一些调试打印,并且为简单起见将类创建限制为两个。这很奇怪:
>>> a = A()
<class '__main__.A'> incrementing
increment parent of <class '__main__.A'> as well
<class '__main__.Countable'> incrementing
@A Counters: 1 As: 1 Bs: 1 B2s: 1
>>> B.counter
1
>>> B.counter is A.counter
True
>>> b = B()
<class '__main__.B'> incrementing
increment parent of <class '__main__.B'> as well
<class '__main__.Countable'> incrementing
@B Counters: 2 As: 1 Bs: 2 B2s: 2
>>> B.counter is A.counter
False
为什么 B() 还没有初始化,它指向与 A.counter 相同的变量,但在创建单个对象后它是不同的?
【问题讨论】:
-
我无法重现您的输出。我对
B2s的输出始终与Bs相同。 -
我用问题的简化示例编辑了您的问题。这是一个有趣的问题,希望有人能解释一下这个过程
-
@Rawing 你是对的,我粘贴了另一个示例的输出......现在我修复它!
-
你知道python有
__subclasses__,它会给你一个类的子类吗? stackoverflow.com/a/3862957/7432
标签: python python-2.7 inheritance class-variables