python中的cls vs.self vs.Class调用
我是Python的初学者,使用Lutz的书来理解python中的cls vs.self vs.Class调用,python,class,object,self,Python,Class,Object,Self,我是Python的初学者,使用Lutz的书来理解classmethod、staticmethod和instancemethod。本代码的目的是通过计算创建的实例数来了解cls、self和直接类调用(Spam1.numInstances)之间的差异 这里有一个从这本书中衍生出来的例子。我不确定为什么父类(Spam1)属性(numInstances)在通过子类Sub1和Other1调用时不递增 这是我的密码: class Spam1: numInstances = 0 def cou
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
的“无参考”。我很沮丧,读了几篇文章:,和,但我不明白发生了什么
具体来说,我的问题如下:
a)为什么创建d
、e
和f
时Spam1.numInstances
没有增加?
以下是我试图回答的问题:
a、 i)据我所知,cls
用于访问类属性。对于d
和e
,self.numInstances
用于访问实例属性,该属性为零,因为Sub1
将继承属性numInstances
的值从Spam1
归零cls
访问Sub1
的class属性,该属性与Sub1
类的属性相同。因此,我们在输出中看到的self
和cls
值分别是Sub1
实例和类的值。我的理解正确吗
a、 ii)f
从Spam1
继承numInstances
。因此,f的self.numInstances
和cls.numInstances
从Spam1
获取值。由于cls
指的是Other1
,而self
指的是f
,它是Other1
的对象,因此它们的值是递增的,但不是Spam1
。因此,Spam1
的numInstances
从未被触碰过
b)我对self.numInstances
、cls.numInstances
和Spam1.numInstances
之间差异的理解是否正确?如果没有,有人能解释一下吗?
我相信我的问题很基本。我希望有人能帮助我。我迷路了。当您处理Sub1
的实例时,Spam1
的numInstances
属性是不可访问的(除了显式写入Spam1.numInstances
)<count()
中的code>cls
指的是Sub1
,该属性在该类中找到,因此无需进一步查找继承链
当您处理
Other1
的实例时,对numInstances
的初始读取确实来自Spam1
——但一旦您分配了一个值,它就会进入Other1
(因为cls
现在是Other1
),现在,所有对该名称的进一步引用都会发现它取代了Spam1的版本
代码中有三个名为
numInstances
的不同类属性:两个在定义类Spam1
和Sub1
后立即存在,另一个在创建Other1
的第一个实例后存在,Spam1
的numInstances
属性不可访问(除了显式写入Spam1.numInstances
)<count()
中的code>cls指的是Sub1
,该属性在该类中找到,因此无需进一步查找继承链
当您处理
Other1
的实例时,对numInstances
的初始读取确实来自Spam1
——但一旦您分配了一个值,它就会进入Other1
(因为cls
现在是Other1
),现在,所有对该名称的进一步引用都会发现它取代了Spam1的版本
在您的代码中有三个名为
numInstances
的不同类属性:两个在定义类Spam1
和Sub1
时就存在,另一个在创建Other1
的第一个实例后就存在。您在这里有一些误解:
numInstances
的实例属性self.numInstances
检查实例属性,但由于没有为self.numInstances
赋值,因此没有要读取的实例属性,因此对self.numInstances
的访问最终读取类属性f
并不完全“继承”父类的值。当执行cls.numInstances+=1
时,它尝试查找Other1.numInstances
,发现它不存在,并检查超类,最终找到Spam1.numInstances
。它增加该值,然后将其分配回其他1。numInstances
(Python中的+=
总是重新分配,即使它在适当的位置执行工作,对于不可变的int
,工作也不在适当的位置);将来,对Other1.numInstances
的访问将不会检查Spam1.numInstances
,因为Other1
的属性现在已经存在你有一些误解:
numInstances
的实例属性self.numInstances
检查实例属性,但因为没有为