我是Python的初学者,使用Lutz的书来理解classmethod
、staticmethod
和{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
显示“no reference”。由于沮丧,我读了一些这样的帖子:What does cls() function do inside a class method?,What is the 'cls' variable used for in Python classes?,和{a3},但我不明白到底发生了什么。在
具体来说,我的问题是:
a)为什么在创建d
、e
和{Spam1.numInstances
没有增加?
我想回答这个问题:
我的理解是cls
用于访问类属性。对于d
和e
,使用self.numInstances
访问实例属性,因为Sub1
将Spam1
继承的属性numInstances
的值归零。cls
访问Sub1
的class属性,这与Sub1
类的属性相同。因此,我们在输出中看到的self
和{Sub1
实例和类。我的理解正确吗?
a.ii)f
从Spam1
继承{self.numInstances
和{Spam1
中的值。它们的值是递增的,但不是Spam1
,因为cls
引用Other1
,因为{Spam1
的numInstances
永远不会被触摸。
b)我对self.numInstances
、cls.numInstances
和{
我认为我的问题很基本。我希望有人能帮我。我迷路了。在
你有几个误解:
numInstances
的实例属性。self.numInstances
检查是否有实例属性,但由于没有任何将分配给self.numInstances
,因此没有实例属性可读取,因此对{f
并不完全“继承”父类的值。当执行cls.numInstances += 1
时,它试图查找Other1.numInstances
,发现它不存在,并检查超类,最终找到Spam1.numInstances
。它增加该值,然后将其赋值回Other1.numInstances
(+=
),即使它在适当的地方完成了工作,它也总是重新分配,对于不可变的{Other1.numInstances
的访问将不会检查Spam1.numInstances
,因为{当您使用},并且该属性位于该类中,因此无需进一步查找继承链。在
Sub1
的实例时,Spam1
的numInstances
属性是不可访问的(除了显式地写入Spam1.numInstances
);count()
中的cls
引用{当您使用}的版本。在
Other1
的实例时,numInstances
的初始读取确实来自Spam1
-但是一旦您分配了一个值,这个值就会进入Other1
(因为cls
现在是Other1
),所有对该名称的进一步引用都会发现它不是{在您的代码中有三个不同的类属性,名为}定义后立即存在,另一个在{}的第一个实例创建后存在。在
numInstances
:两个在类Spam1
和{相关问题 更多 >
编程相关推荐