我希望以下代码可以打印012345但它打印012012。为什么?我希望对 incr 的调用访问相同的变量,因为它们是从同一个类继承的,但它们显然是不同的变量。
class a(object):
var = 0
@classmethod
def incr(cls):
print cls.var
cls.var+=1
class b(a):
def func(self):
super(b,self).incr()
class c(a):
def func(self):
super(c,self).incr()
t = a()
t1 = b()
t2 = c()
t1.func()
t1.func()
t1.func()
t2.func()
t2.func()
t2.func()
它们继承自同一类,但通过 super 传递给classmethod
的cls
是调用该方法的当前类。super
访问方法的基类版本,但调用的cls
是进行超级调用的类。
这是执行操作之间的细微区别之一:
def func(self):
super(c, self).incr() # same as a.__dict__['incr'].__get__(self, type(self))()
和:
def func(self):
a.incr()
在这两种情况下,您都可以通过在incr
方法中打印当前cls
来确认这一点:
def incr(cls):
print cls
...
您永远不应该假设super
所做的只是进行绑定到父类的方法调用。它的作用远不止于此。
请记住,当执行第一个增强赋值+=
时,将从基类读取var
的初始值(因为此时它不存在于子类的字典中(。但是,更新的值将写入子类。从第二个子类调用super
会重复从a
读取初始var
值的相同行为。
有一种方法可以生成序列012345。必须确保类a
的var
在incr
方法中增加,即使在子类中调用时也是如此。 为此,请按a.var += 1
递增,而不是按cls.var += 1
递增。
正如其他答案所指出的,var
也被继承到b
和c
。 通过使用cls.var += 1
两个子类都增加了自己的var
而不是a
的var
。
class a:
var = 0
@classmethod
def incr(cls):
print(cls.var)
a.var += 1
class b(a):
def f(self):
super().incr()
class c(a):
def f(self):
super().incr()
cb = b()
cc = c()
cb.incr()
cb.incr()
cb.incr()
cc.incr()
cc.incr()
cc.incr()
cb.incr()
cc.incr()
生产:
0
1
2
3
4
5
6
7
类b
和类c
分别从类a
继承,每次var
都设置为 0。
让类c
在类a
中获取与类b
相同的var
值的一种方法是,类c
可以从类b
继承,如下所示:
class a(object):
var = 0
@classmethod
def incr(cls):
print cls.var
cls.var+=1
class b(a):
def func(self):
super(b,self).incr()
class c(b):
def func(self):
super(c,self).incr()
t = a()
t1 = b()
t2 = c()
t1.func()
t1.func()
t1.func()
t2.func()
t2.func()
t2.func()`