我不完全了解,以下示例中的类属性整数或列表的区别是什么:
class MyClass(object):
a = [1]
b = 1
def __init__(self):
print(self.a, id(MyClass.a))
print(self.b, id(MyClass.b))
def modify(self):
self.a.append(2)
print("modfied list attribute:", MyClass.a, id(MyClass.a))
print("modfied listattribute:", self.a, id(self.a))
self.b += 1
print("modfied int attribute:", MyClass.b, id(MyClass.b))
print("modfied int attribute:", self.b, id(self.b))
x = MyClass()
x.modify()
y = MyClass()
在此示例的输出中,可以看到,如果我在一个实例(x)中更改了列表,则MyClass中的实际属性也会被更改。但是,在一个实例中更改该整数后,该类的整数将保持不变。我认为,这与列表的功能有关,即,如果附加了某些值,则ID将保留。
有人可以简要地给我一个简短的解释,这种行为背后的主要原因是什么?
答案 0 :(得分:3)
int
的值是不可变的。您没有修改现有的int
,而是用不同 self.b
的值替换了int
。
list
的值 是可变的,并且list.append
修改调用它的实例。 self.a
被就地修改,而不用新列表替换现有列表。
基本上,如果不知道+=
的值类型,就无法预测其行为。在b = 0; b += 1
中,b
指的是int
的新实例。但是在b = []; b += [2,3]
中,现有列表得到了扩展(就像您曾经呼叫过b.extend([2,3])
一样。)
答案 1 :(得分:0)
看看如何使用is语句(不使用==)使它可视化:
class MyClass(object):
a = [1]
b = 1
def __init__(self):
print(self.a, id(MyClass.a))
print(self.b, id(MyClass.b))
def modify(self):
self.a.append(2)
print("modfied list attribute:", MyClass.a, id(MyClass.a))
print("modfied listattribute:", self.a, id(self.a))
self.b += 1
print("modfied int attribute:", MyClass.b, id(MyClass.b))
print("modfied int attribute:", self.b, id(self.b))
x = MyClass()
y = MyClass()
print(x.a is y.a) # True
print(x.b is y.b) # True
x.modify()
print(x.a is y.a) # True
print(x.b is y.b) # Falseclass MyClass(object):
a = [1]
b = 1
def __init__(self):
print(self.a, id(MyClass.a))
print(self.b, id(MyClass.b))
def modify(self):
self.a.append(2)
print("modfied list attribute:", MyClass.a, id(MyClass.a))
print("modfied listattribute:", self.a, id(self.a))
self.b += 1
print("modfied int attribute:", MyClass.b, id(MyClass.b))
print("modfied int attribute:", self.b, id(self.b))
x = MyClass()
y = MyClass()
# Before changing something a and b is a reference to the same object
print(x.a is y.a) # True
print(x.b is y.b) # True
x.modify()
# After that only x.b is a reference to a new object
# you accessed the list object that is shared and append a value
print(x.a is y.a) # True
print(x.b is y.b) # False
# If you would give x.a a new list it would look like this
x.a = []
print(x.a is y.a) # False
print(x.b is y.b) # False
# x.a is now not the same list as y.a
除非您有理由使用a和b作为类属性,否则我建议您将其设置为实例属性:
class MyClass(object):
def __init__(self):
self.a = [1]
self.b = 1
print(self.a, id(self.a))
print(self.b, id(self.b))
def modify(self):
self.a.append(2)
print("modfied list attribute:", self.a, id(self.a))
print("modfied listattribute:", self.a, id(self.a))
self.b += 1
print("modfied int attribute:", self.b, id(self.b))
print("modfied int attribute:", self.b, id(self.b))
x = MyClass()
y = MyClass()
print(x.a is y.a) # False
print(x.b is y.b) # False
x.modify()
print(x.a is y.a) # False
print(x.b is y.b) # False
x.a = []
print(x.a is y.a) # False
print(x.b is y.b) # False