为什么类变量会改变?

时间:2013-09-13 14:32:01

标签: python

所以我在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?

4 个答案:

答案 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.mapMap.map都指向同一个列表。用Python的说法,self.mapMap.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]

哪个更容易理解。

一般来说,可变类变量是一个坏主意,除了一些非常具体的情况。