2

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

>>> 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]
>>> 

为什么是这样?

以及如何防止这种情况发生——我想alistblist(不可变的,如果你愿意的话)的更改不感兴趣?

4

5 回答 5

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 返回给定对象的内存地址。由于两个列表都相同,这意味着更改一个会影响另一个,因为它们实际上是同一件事。

于 2013-07-18T12:49:56.903 回答
9

Variable binding in Python works this way: you assign an object to a variable.

a = 4
b = a

Both point to 4.

b = 9

Now b points to somewhere else.

Exactly the same happens with lists:

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

Now, b has a new value, while a has the old one.

Till now, everything is clear and you have the same behaviour with mutable and immutable objects.

Now comes your misunderstanding: it is about modifying objects.

lists are mutable, so if you mutate a list, the modifications are visible via all variables ("name bindings") which exist:

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
于 2013-07-18T12:51:12.830 回答
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 文档的相关引用。

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

于 2013-07-18T12:47:17.087 回答
1

Based on this post:

Python passes references-to-objects by value (like Java), and everything in Python is an object. This sounds simple, but then you will notice that some data types seem to exhibit pass-by-value characteristics, while others seem to act like pass-by-reference... what's the deal?

It is important to understand mutable and immutable objects. Some objects, like strings, tuples, and numbers, are immutable. Altering them inside a function/method will create a new instance and the original instance outside the function/method is not changed. Other objects, like lists and dictionaries are mutable, which means you can change the object in-place. Therefore, altering an object inside a function/method will also change the original object outside.

So in your example you are making the variable bList and aList point to the same object. Therefore when you remove an element from either bList or aList it is reflected in the object that they both point to.

于 2013-07-18T12:51:47.230 回答
0

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

您正在 Python 文档中寻找官方参考资料。看看这个部分: http ://docs.python.org/2/reference/simple_stmts.html#assignment-statements

引用后者:

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

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

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

于 2013-07-18T12:56:44.143 回答