问题描述
在尝试这段代码时:
class A:
mutable = {}
number =10
def change(cls):
cls.mutable[cls] = "true"
cls.number = cls.number +10
print (cls.mutable)
print (cls.number)
obj1 = A()
obj2 = A()
print (obj1.change())
print (obj1.change())
print (obj1.change())
print(obj2.change())
print (obj2.change())
print (obj2.change())
有人可以帮忙吗?这将是很大的帮助
{<__main__.A object at 0x000002101CB3B940>: 'true'}
20
None
{<__main__.A object at 0x000002101CB3B940>: 'true'}
30
None
{<__main__.A object at 0x000002101CB3B940>: 'true'}
40
None
{<__main__.A object at 0x000002101CB3B940>: 'true',<__main__.A object at 0x000002101CBA6630>: 'true'}
20
None
{<__main__.A object at 0x000002101CB3B940>: 'true',<__main__.A object at 0x000002101CBA6630>: 'true'}
30
None
{<__main__.A object at 0x000002101CB3B940>: 'true',<__main__.A object at 0x000002101CBA6630>: 'true'}
40
None
解决方法
您所看到的是可变对象和不可变对象之间的区别。
您的变量mutable
是可变的dict
。您的变量number
是不可变的int
。
让我们从您的类定义开始。
class A:
mutable = {}
number = 10
在这里设置2个类属性。由于其中只有一个是可变的,因此修改后,只有一个会继续成为同一对象。
接下来让我们谈谈您的方法。
def change(cls):
cls.mutable[cls] = "true"
cls.number = cls.number + 10
print(cls.mutable)
print(cls.number)
在这里,您的cls
变量有点欺骗。正如@MisterMiyagi提到的,这不是一个类方法。通常,我们将命名为self
中传递的隐式实例变量。命名cls
不会改变它的行为,因为名称self
没有什么特别的地方。使用该名称只是一种惯例。
这里的另一点重要之处在于,尽管这一行cls.mutable[cls] = "true"
改变了现有的类属性,但该cls.number = cls.number + 10
创建了一个新鲜的对象并将其分配给实例,因为cls
实际上是指在这种情况下转到实例。
总而言之,在您第一次调用change
方法时。 cls.number = cls.number + 10
分配的实例属性等于类属性加10。
当然,您可以通过给它一个@classmethod
装饰器来更改此行为,该装饰器将隐式传递该类而不是实例。
@classmethod
def change(cls):
cls.mutable[cls] = "true"
print(id(cls.number))
cls.number = cls.number + 10
print(id(cls.number))