用Python共享全局数据

Har*_* Ma 5 python class list

我正在构建一个需要全局共享数据的项目.我构建了一个类GlobalDataBase来处理这些数据,就像我如何避免在实例之间共享类数据一样?https://docs.python.org/2/tutorial/classes.html.但是,我发现了一些有点奇怪的东西.我的代码如下:

class GlobalDataBase:

    a = []

    def copy_to_a(self, value):
        self.a = value  

    def assign_to_a(self, value):
        for idx in range(0, len(value)):
            self.a.append(value[idx])

def test_copy():

    gb1 = GlobalDataBase()
    gb1.copy_to_a([1,2])
    print gb1.a

    gb2 = GlobalDataBase()
    print gb2.a


def test_assign():

    gb1 = GlobalDataBase()
    gb1.assign_to_a([1,2])
    print gb1.a

    gb2 = GlobalDataBase()
    print gb2.a
Run Code Online (Sandbox Code Playgroud)

输出test_copy

[1,2]

[]
Run Code Online (Sandbox Code Playgroud)

输出test_assign

[1,2]

[1,2]
Run Code Online (Sandbox Code Playgroud)

第二种方法的结果就是我所期待的.但我无法理解为什么第一种方法不起作用.谁能解释这两种方法之间的区别?

Kor*_*rem 4

a被分配了一个关于 的GlobalDataBase声明的列表。每个实例都以对同一列表的引用GlobalDataBase开始,我们将其称为“原始”列表。

当您self.a = value在第一个示例中执行此操作时,对于该实例或“self”,您将对原始列表的引用替换为对value您分配的列表的引用。创建的任何新实例仍将引用原始列表,这就是为什么gb2打印出一个空列表 - 原始列表,而不是[1,2]- 新列表。

让我们看看它是如何工作的,使用id

声明后,GlobalDataBase保留对以下内容的引用a

id(GlobalDataBase.a)
Out[112]: 290675912L #Original
Run Code Online (Sandbox Code Playgroud)

我们创建的任何实例都持有相同的引用:

gb1 = GlobalDataBase()
id(gb1.a)
Out[114]: 290675912L #Original
Run Code Online (Sandbox Code Playgroud)

之后copy_to_a,您可以看到它发生了变化:

gb1.copy_to_a([1,2])
id(gb1.a)
Out[116]: 290670536L #Changed!
Run Code Online (Sandbox Code Playgroud)

gb2仍然有原始参考:

id(gb2.a)
Out[118]: 290675912L #Original
Run Code Online (Sandbox Code Playgroud)

您说您理解第二个示例,但为了完整性,当您理解时,self.a.append(value[idx])您将附加到原始列表。如前所述,新实例会引用该列表,并“看到”该更改。

在这里我们可以看到引用没有改变:

gb1 = GlobalDataBase()
id(gb1.a)
Out[120]: 290675912L #Original

gb1.assign_to_a([1,2])
id(gb1.a)
Out[122]: 290675912L #Original

gb2 = GlobalDataBase()
id(gb2.a)
Out[124]: 290675912L #Original
Run Code Online (Sandbox Code Playgroud)