为什么列表在Python中以持久的方式链接?

时间:2013-07-18 12:45:49

标签: python list immutability

设置变量。另一个变量设置为第一个。第一个改变了价值。第二个没有。从一开始就是编程的本质。

>>> a = 1
>>> b = a
>>> b = b - 1
>>> b
0
>>> a
1

然后我将它扩展到Python列表。声明并附加列表。宣布另一个列表与第一个列表相同。第二个列表中的值发生变化。神秘的是,第一个列表中的值虽然没有直接作用,但也会发生变化。

>>> alist = list()
>>> blist = list()
>>> alist.append(1)
>>> alist.append(2)
>>> alist
[1, 2]
>>> blist
[]
>>> blist = alist
>>> alist.remove(1)
>>> alist
[2]
>>> blist
[2]
>>> 

这是为什么?

我如何防止这种情况发生 - 我希望alist更改blist(不可变,如果你愿意)?

5 个答案:

答案 0 :(得分:10)

Python变量实际上是不是变量,而引用到对象(类似于C中的指针)。对http://foobarnbaz.com/2012/07/08/understanding-python-variables/

中的初学者有一个非常好的解释

说服自己的一种方法是试试这个:

a=[1,2,3]
b=a
id(a)
68617320
id(b)
68617320

id返回给定对象的内存地址。由于两个列表的两个都相同,这意味着更改一个会影响另一个,因为它们实际上是相同的。

答案 1 :(得分:9)

Python中的变量绑定以这种方式工作:将对象分配给变量。

a = 4
b = a

两者都指向4

b = 9

现在b指向其他地方。

列表恰好相同:

a = []
b = a
b = [9]

现在,b有一个新值,而a有旧值。

到目前为止,一切都很清楚,你对可变和不可变对象有相同的行为。

现在出现了你的误解:它是关于修改对象。

list是可变的,所以如果你改变列表,修改是通过存在的所有变量(“名称绑定”)可见的:

a = []
b = a  # the same list
c = [] # another empty one

a.append(3)
print a, b, c # a as well as b = [3], c = [] as it is a different one

d = a[:] # copy it completely
b.append(9)
# now a = b = [3, 9], c = [], d = [3], a copy of the old a resp. b

答案 2 :(得分:4)

当您执行以下操作时,您将创建对同一列表的另一个引用:

blist = alist

因此,blist引用alist所做的相同列表。因此,对该单个列表的任何修改都会影响alistblist

如果要复制整个列表,而不仅仅是创建引用,则可以执行以下操作:

blist = alist[:]

事实上,您可以使用id()

自行检查参考文献
>>> alist = [1,2]
>>> blist = []
>>> id(alist)
411260888
>>> id(blist)
413871960
>>> blist = alist
>>> id(blist)
411260888
>>> blist = alist[:]
>>> id(blist)
407838672

这是Python docs.

的相关引用
  

Python中的赋值语句不复制对象,它们在目标和对象之间创建绑定。对于可变或包含可变项目的集合,有时需要一个副本,因此可以更改一个副本而不更改另一个副本。

答案 3 :(得分:1)

基于此post

  

Python按值传递对象的引用(如Java),和   Python中的所有东西都是一个对象。这听起来很简单,但随后你   会注意到某些数据类型似乎表现出传值   特征,而其他似乎像传递参考...   这是什么交易?

     

理解可变和不可变对象很重要。一些   对象,如字符串,元组和数字,是不可变的。涂改   它们在函数/方法内部将创建一个新实例和   函数/方法之外的原始实例不会更改。其他   对象,如列表和词典是可变的,这意味着你可以   就地更改对象。因此,改变一个内部的对象   function / method也会改变外面的原始对象。

因此,在您的示例中,您将变量bListaList指向同一个对象。因此,当您从bListaList中删除元素时,它会反映在它们都指向的对象中。

答案 4 :(得分:0)

简短回答两个问题“为什么会这样?”:因为在Python中整数是不可变的,而列表是可变的。

您正在寻找Python文档中的官方参考。看看这一节: http://docs.python.org/2/reference/simple_stmts.html#assignment-statements

引用后者:

  

赋值语句用于(重新)将名称绑定到值和   修改可变对象的属性或项目

我真的很喜欢这句话,以前从未见过。它准确地回答了你的问题。

关于这个主题的最近一篇好文章是http://nedbatchelder.com/text/names.html,其中一篇评论已经提到过。