【发布时间】:2018-12-22 08:58:28
【问题描述】:
我是 Python 初学者,通过 Lutz 的书了解classmethod、staticmethod 和instancemethod。这段代码的目的是通过计算创建的实例数来了解cls、self 和直接类调用 (Spam1.numInstances) 之间的区别。
这是从这本书中衍生出来的一个例子。我不确定为什么父类 (Spam1) 属性 (numInstances) 在通过子类 Sub1 和 Other1 调用时不会增加。
这是我的代码:
class Spam1:
numInstances = 0
def count(cls):
cls.numInstances += 1
print("In count -> number of instances: cls, Spam", cls.numInstances, Spam1.numInstances)
def __init__(self):
print("-----")
print("In init, before -> number of instances: self, Spam",self.numInstances,Spam1.numInstances )
self.count()
print("In init, after -> number of instances: self, Spam",self.numInstances,Spam1.numInstances )
print("-----")
count=classmethod(count)
class Sub1(Spam1):
numInstances = 0
class Other1(Spam1):
pass
a=Spam1() #Output after increment: 1,1,1 (self, cls, Spam1)
b=Spam1() #Output after increment: 2,2,2 (self, cls, Spam1)
c=Spam1() #Output after increment: 3,3,3 (self, cls, Spam1)
d=Sub1() #Output after increment: 1,1,3 (self, cls, Spam1)
e=Sub1() #Output after increment: 2,2,3 (self, cls, Spam1)
f=Other1() #Output after increment: 4,4,3 (self, cls, Spam1)
我花了一天时间尝试调试此代码,但我无法理解 cls.numInstances 的工作原理,因为 PyCharm 在调试模式下会显示 cls.numInstances 的“无参考”。感到沮丧,我阅读了一些 SO 主题:What does cls() function do inside a class method?、What is the 'cls' variable used for in Python classes? 和 Python - self, no self and cls,但我无法理解发生了什么。
具体来说,这是我的问题:
a) 为什么在创建d、e 和f 时Spam1.numInstances 没有增加?
这是我试图回答这个问题的尝试:
a.i) 据我了解,cls 用于访问类属性。对于d 和e,self.numInstances 用于访问实例属性,该属性为零,因为Sub1 将来自Spam1 的继承属性numInstances 的值归零。 cls 访问Sub1 的类属性,这也与Sub1 类的属性相同。因此,我们在输出中看到的self 和cls 值分别是Sub1 实例和类。我的理解正确吗?
a.ii) f 从 Spam1 继承 numInstances。因此,f 的 self.numInstances 和 cls.numInstances 采用来自 Spam1 的值。它们的值是递增的,但不是 Spam1,因为 cls 引用 Other1 并且因为 self 引用 f,这是 Other1 的对象。因此,Spam1 的 numInstances 永远不会被触及。
b) 我对self.numInstances、cls.numInstances 和Spam1.numInstances 之间差异的理解是否正确?如果不是,有人可以解释一下吗?
我相信我的问题是非常基本的。我希望有人能帮助我。我迷路了。
【问题讨论】:
-
重要的是要了解
self和cls在这里只是常规名称。他们可能是foo或banana。它们的特别之处在于它们是第一个参数,因此当在实例上调用时它们会隐式传递给实例(以及当您使用classmethod装饰器时的类)