1

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

4 回答 4

5

你想要的是这样的:

    self.map = Map.map[:]

原因是当你这样做的时候self.map = Map.mapself.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
于 2013-09-13T14:34:35.003 回答
1

在 Python 中,赋值不是复制!它只是给你另一个名字来访问同一个对象。

如果对象是不可变的,例如数字或字符串,您将不会注意到差异。但是,当您对可变对象(例如列表)进行分配时,对该对象所做的任何更改都会反映在所有其他分配的名称中,因为它们仍然是同一个对象。

要制作列表的副本,您可以使用切片表示法(切片进行复制),也可以使用copy模块

于 2013-09-13T14:48:24.250 回答
0

self.map并且Map.map都指向同一个列表。在 Python 用语中,self.mapMap.map都是同一个列表的名称。

看看是不是id(self.map) == id(Map.map),你会发现是True

要获得您想要的行为,请将 Map.map的副本分配给 self.map。

使用任一list()

self.map = list(Map.map)

或切片语法

self.map = Map.map[:]

内置的复制模块也可以用于此,特别是如果您有嵌套列表。

于 2013-09-13T14:37:12.017 回答
-1

As others have noted, it's because you are using a mutable class variable.

As you are using the same list for all instances, having a class variable is pointless.

class Map():
    map = [1,2,3]
    def __init__(self):
        self.map = Map.map[:]

Is completely functionally equivalent with:

class Map():
    def __init__(self):
        self.map = [1,2,3]

Which is much easier to understand.

In general, mutable class variables is a bad idea, except for some very specific circumstances.

于 2013-09-13T14:43:46.017 回答