所以我在python中编写了一些内容,它将一个类变量赋值给一个实例变量,然后在 init 方法中更改实例变量。我稍微简化了代码,当我运行它时,类变量也会被更改:
class Map():
map = [1,2,3]
def __init__(self):
self.map = Map.map
for i in range(len(self.map)):
self.map[i] = self.map[i] * 2
print("self.map =", self.map)
print("Map.map =", Map.map)
new_map = Map()
当我运行它时,我得到以下输出:
self.map = [1, 4, 9]
Map.map = [1, 4, 9]
基本上我想知道为什么Map.map会改变,即使我只改变了self.map?
答案 0 :(得分:5)
你想要的是这个:
self.map = Map.map[:]
原因是当您执行self.map = Map.map
时,self.map
指向与Map.map
相同的对象。所以,当你变异self.map
时,你也会改变Map.map
,因为它是同一个对象。这与现在的情况相同:
>>> a = [1, 2, 3]
>>> b = a
>>> b[0] = 4
>>> a
[4, 2, 3]
>>> b is a
True
您想要做的是复制对象。您可以通过list(a)
或a[:]
:
>>> a = [1, 2, 3]
>>> b = a[:]
>>> b[0] = 4
>>> a
[1, 2, 3]
>>> b
[4, 2, 3]
>>> b is a
False
答案 1 :(得分:1)
在Python中,赋值不是复制!它只是为您提供了另一个名称来访问同一个对象。
如果对象是不可变的,例如数字或字符串,您将不会注意到差异。但是当你对一个可变对象(如列表)进行赋值时,对该对象所做的任何更改都会反映在所有其他已分配的名称中,因为它们仍然是同一个对象。
要制作列表的副本,您可以使用切片表示法(切片可以复制),也可以使用the copy
module。
答案 2 :(得分:0)
self.map
和Map.map
都指向同一个列表。用Python的说法,self.map
和Map.map
都是同一列表的名称。
检查是否id(self.map) == id(Map.map)
,您会发现它是True
。
要获得所需的行为,请将Map.map的assign a copy改为self.map。
使用list()
self.map = list(Map.map)
或切片语法
self.map = Map.map[:]
builtin copy module也可以用于此,特别是如果你有嵌套列表。
答案 3 :(得分:-1)
正如其他人所说,这是因为你正在使用一个可变的类变量。
当您对所有实例使用相同的列表时,拥有类变量是没有意义的。
class Map():
map = [1,2,3]
def __init__(self):
self.map = Map.map[:]
在功能上完全等同于:
class Map():
def __init__(self):
self.map = [1,2,3]
哪个更容易理解。
一般来说,可变类变量是一个坏主意,除了一些非常具体的情况。