说我有一堂课:
class Thing:
i = 0
def __init__(self, a):
self.a = a
def doStuff(self):
print(self.a)
@classmethod
def doClassThings(cls):
cls.i += 1
然后,我从此类创建了两个对象:
obj1 = Thing(2)
obj2 = Thing(4)
此时程序的内存中有多少个“ doStuff”和“ init ”方法实例?对于两个对象中的每一个,是否都有这些方法的单独但相同的副本?还是只有两个事物实例共享一个“ doStuff”方法?
对于类方法,我的理解是每个类方法只有一个实例,可以通过编写来调用
Thing.doClassThings()
整个班级也只有一个“ i”变量。这是正确的吗?
无论哪种方式,就实例方法而言,就内存使用而言,我都不知道Python如何工作。我真的很不喜欢这些实例方法有副本的想法,因为它们是相同的,而且这是多余的。
最后,如果Python确实为该类的每个实例创建了每个实例函数的多个副本,那么我该如何编写不这样做的代码?
答案 0 :(得分:0)
请注意,我不知道具体的规格,以下只是我的观察和预测。
此时程序的内存中有多少个“ doStuff”和“ init”方法实例?对于两个对象中的每一个,是否都有这些方法的单独但相同的副本?还是只有两个事物实例共享一个“ doStuff”方法?
如果您打印doStuff
和__init__
,则会看到它们具有不同的内存地址: print(ob1.doStuff)
(不要在后面加上括号,因为我们不想调用该函数)给了我<bound method Thing.doStuff of <__main__.Thing object at 0x0000026FE45C9128>>
,但是print(obj.doStuff)
打印了<bound method Thing.doStuff of <__main__.Thing object at 0x0000026FE45C9160>>
;这两个功能具有不同的存储器地址。因此,确实有两个单独但相同的方法副本。
对于类方法,我的理解是每个类方法只有一个实例,可以通过编写
来调用Thing.doClassThings()
这应该是正确的(打印函数不会给我地址,但是使用==
比较两个函数会返回True
。)。尽管您也可以从对象本身(例如obj.doClassThings()
)调用该函数。
整个班级也只有一个“ i”变量。这是正确的吗?
这似乎有点不可思议:
print(obj1.i, obj2.i, Thing.i) # prints 0 0 0, as expected
Thing.doClassThings()
print(obj1.i, obj2.i, Thing.i) # prints 1 1 1
obj1.i += 1
print(obj1.i, obj2.i, Thing.i) # prints 2 1 1
Thing.doClassThings()
print(obj1.i, obj2.i, Thing.i) # prints 2 2 2
就像您从对象中更改i
一样,它会创建自己的i
,而不连接到其余对象。