Python永久赋值变量

时间:2010-08-27 02:23:16

标签: python list reference

我刚开始使用python并遇到了一些奇怪的事情。

以下代码为变量test指定了x = 1和y = 2的坐标。 test2变量为test赋值相同的值,然后test2的[x]值更改为旧的[x]值减1.这样可以正常工作,但是,当执行最后一部分时,它不仅减去1从test2中的[x]值开始,它也与测试变量中的[x]值相同。

test = [1,2];
test2 = test;
test2[1] = test2[1] - 1;

我发现以下工作正常但我仍然不明白为什么第一种方法会更改测试值以及test2值。

test = [1,2];
test2 = test;
test2 = [test2[0] -1 ,test2[1]];

有人可以解释为什么会这样。

谢谢 TheLorax

4 个答案:

答案 0 :(得分:4)

在Python中,就像在Java中一样,赋值本身永远不会复制 - rahter,赋值将另一个引用添加到与右边相同的对象=。 (参数传递以相同的方式工作)。奇怪的是,你从未听说过这个概念,当Python非常流行并且Java更加如此(以及许多其他语言倾向于以类似的方式工作,可能会带来更多的复杂性或区别)。

当您想要副本时,您要求获取副本(作为右侧表达式的一部分,或者习惯于获取参数你过世了!)在Python中,根据您的确切目的,有几种方法 - 标准库的copy模块是受欢迎的(带有函数copy,用于“浅”副本,{{1}当然,对于“深层”副本,即不仅仅是容器,而是每个包含的项目,也会被递归深度复制。“

但是,通常,您想要的是“新列表” - 无论原始序列是列表,副本还是可迭代的其他内容,您可能不关心:您需要新的deepcopy实例,其项目与“别的东西”相同。表达这一点的最佳方式是使用list - 调用list(somethingelse)类型,它始终生成列表的新实例,并将其作为参数提供给新列表中所需项目的迭代项。同样,list创建一个新的dict(somemapping)dict创建一个新的集合 - 调用一个类型来创建该类型的新实例是一个非常通用和有用的概念!

答案 1 :(得分:3)

这是因为当您执行test2 = test时,您不是要复制列表的内容,而是简单地为test2分配对原始列表的引用。因此,对test2的任何更改也会影响test

正确的方法是使用复制模块中的deepcopy()(或copy(),如果您可以使用浅色副本。

import copy
test2 = copy.deepcopy(test) # deep copy

test2 = copy.copy(test)) # shallow copy

test2 = test[:] # shallow copy using slices

有关更深入的说明以及复制列表的其他方法,请参阅this page

答案 2 :(得分:0)

[1,2]是一个数组,当您将其分配给test时,您将分配对该数组的引用以进行测试。因此,当您执行test2=test时,您将分配对另一个变量的引用。对任何变量进行更改,数组将被更改。

您的第二个示例有效,因为您完全创建了一个新数组。你不妨这样做:

test = [1,2]
test2 = [test[0]-1, test[1]]

答案 3 :(得分:0)

Python不做任务。

它确实命名绑定。

存在差异,并且详细解释here

在你的第一个例子中: 第一行将名称“test”绑定到由“[1,2]”表达式创建的列表对象。 第二行将名称“test2”绑定到与“test”绑定的相同对象。 你的第三行改变绑定到“test2”的对象,这与“test”绑定的对象相同。

在你的第二个例子中: 第一行将名称“test”绑定到由“[1,2]”表达式创建的列表对象。 第二行将名称“test2”绑定到与“test”绑定的同一对象。 第三行将名称“test2”绑定到 new 对象,该对象由表达式“[test2 [0] -1,test2 1]”创建。

如果您真的想要两个具有相同值的独立列表绑定到不同的变量,则需要:

>>> test = [1, 2]
>>> test2 = list(test)
>>> test2[0] = 3
>>> print(test)
[1, 2]
>>> print(test2)
[3, 2]

请注意,这是一个浅拷贝列表,因此,如果在该列表中找到相同的对象,则更改test2中元素对象的状态将会影响test

P.S。蟒蛇。分号。丑陋。不必要。不使用。