我正在构建一个需要全局共享数据的项目.我构建了一个类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)
第二种方法的结果就是我所期待的.但我无法理解为什么第一种方法不起作用.谁能解释这两种方法之间的区别?
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)
| 归档时间: |
|
| 查看次数: |
103 次 |
| 最近记录: |