我是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
的“无引用”。感到沮丧的是,我读了一些这样的帖子: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,但我不明白发生了什么。
具体来说,以下是我的问题:
创建Spam1.numInstances
d
**,** e
**,和** f
时,为什么没有增加?a)
以下是我对这个问题的回答:
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
区别的理解是否正确?****cls.numInstances
**,和**有什么区别?如果没有,有人能解释一下吗?
我相信我的问题是非常基本的。我希望有人能帮帮我。我迷路了。
发布于 2018-07-14 09:08:31
你在这里有一些误解:
numInstances
的实例属性。self.numInstances
检查实例属性,但是因为没有任何东西赋值给self.numInstances
,所以没有实例属性可读,因此对self.numInstances
的访问最终读取了类attribute.f
并不完全“继承”父类的值。当cls.numInstances += 1
被执行时,它试图查找Other1.numInstances
,发现它不存在,并检查超类,最终找到Spam1.numInstances
。它递增该值,然后将该值重新赋值给Other1.numInstances
(Python中的+=
总是重新赋值,即使它完成了工作,对于不可变的int
,工作也没有到位);将来,访问Other1.numInstances
将不会检查Spam1.numInstances
,因为Other1
的属性现在存在。发布于 2018-07-14 09:04:58
当您使用Sub1
的实例时,Spam1
的numInstances
属性是不可访问的(除非显式编写Spam1.numInstances
);count()
中的cls
引用Sub1
,并且该属性在该类中找到,因此不需要进一步查找继承链。
当您使用Other1
的实例时,numInstances
的初始读取确实来自Spam1
-但一旦您赋值,它就会进入Other1
(因为cls
现在是Other1
),所有对该名称的进一步引用现在都会发现该名称而不是Spam1
的版本。
代码中有三个名为numInstances
的不同类属性:两个在定义Spam1
和Sub1
类时立即存在,另一个在创建Other1
的第一个实例后存在。
https://stackoverflow.com/questions/51334255
复制相似问题