设置变量。另一个变量设置为第一个。第一个改变了价值。第二个没有。从一开始就是编程的本质。
>>> 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
(不可变,如果你愿意)?
答案 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
所做的相同列表。因此,对该单个列表的任何修改都会影响alist
和blist
。
如果要复制整个列表,而不仅仅是创建引用,则可以执行以下操作:
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也会改变外面的原始对象。
因此,在您的示例中,您将变量bList
和aList
指向同一个对象。因此,当您从bList
或aList
中删除元素时,它会反映在它们都指向的对象中。
答案 4 :(得分:0)
简短回答两个问题“为什么会这样?”:因为在Python中整数是不可变的,而列表是可变的。
您正在寻找Python文档中的官方参考。看看这一节: http://docs.python.org/2/reference/simple_stmts.html#assignment-statements
引用后者:
赋值语句用于(重新)将名称绑定到值和 修改可变对象的属性或项目
我真的很喜欢这句话,以前从未见过。它准确地回答了你的问题。
关于这个主题的最近一篇好文章是http://nedbatchelder.com/text/names.html,其中一篇评论已经提到过。