为什么+运算符不会在.append()的情况下更改列表?

can*_*289 7 python list concatenation append

我正在通过Udacity和Dave Evans介绍了关于列表属性的练习

list1 = [1,2,3,4]
list2 = [1,2,3,4]

list1=list1+[6]
print(list1)
list2.append(6)
print(list2)

list1 = [1,2,3,4]
list2 = [1,2,3,4]

def proc(mylist):
    mylist = mylist + [6]

def proc2(mylist):
    mylist.append(6)

# Can you explain the results given by the four print statements below? Remove
# the hashes # and run the code to check.

print (list1)
proc(list1)
print (list1)

print (list2)
proc2(list2)
print (list2)
Run Code Online (Sandbox Code Playgroud)

输出是

[1, 2, 3, 4, 6]
[1, 2, 3, 4, 6]
[1, 2, 3, 4]
[1, 2, 3, 4]
[1, 2, 3, 4]
[1, 2, 3, 4, 6]
Run Code Online (Sandbox Code Playgroud)

所以在一个函数中,在集合中添加6并没有显示,但是当它不在函数中时它会显示?

bra*_*zzi 15

所以在一个函数中,在集合中添加6并没有显示,但是当它不在函数中时它会显示?

不,这不是发生的事情.

会发生什么,当您执行时mylist = mylist + [6],您正在有效地创建一个全新的列表并将其放在局部mylist变量中.mylist执行该函数后,此变量将消失,新创建的列表也将消失.

OTOH执行mylist.append(6)时不要创建新列表.您将获得mylist变量中的列表,并将新元素添加到同一列表中.结果是列表(也由其指出list2)将自行更改.该mylist变量将再次消失,但在TIS如果你改变了原来的列表中.

让我们看看更直观的解释是否可以帮助你:)

你打电话后会发生什么 proc()

在编写时,list1 = [1, 2, 3, 4, 5]您正在创建一个新的列表对象(在等号的右侧)并创建一个新的变量,list1它将指向此对象.

创建新的列表实例和全局变量

然后,当您调用时proc(),您创建另一个新变量,mylist并且因为您list1作为参数传递,mylist将指向同一个对象:

调用方法创建局部变量

但是,该操作mylist + [6] 会创建一个全新的列表对象,其内容是指向的对象mylist的内容加上以下列表对象的内容 - 即[6].由于您将此新对象归因于此属性mylist,因此我们的方案稍有变化,mylist并且不再指向由此指向的同一对象list1:

mylist指向新列表对象

我没有说的是这mylist 是一个局部变量:它会在proc()函数结束后消失.所以,当proc()执行结束时,mylist它就消失了:

mylist消失了

由于没有其他变量指向生成的对象mylist + [6],它也会消失(因为垃圾收集器*会收集它):

GC收集清单

注意,最后,指向的对象list1不会改变.

你打电话后会发生什么 proc2()

你打电话时一切都会改变proc2().首先,它是一样的:你创建一个列表......

创建新的列表实例和全局变量

...并将其作为参数传递给函数,该函数将生成局部变量:

调用方法创建局部变量

但是,不是使用+生成新列表的串联运算符,而是将该append()方法应用于现有列表.该append()方法不会创建新对象 ; 相反,它_改变现有的:

将值附加到列表

函数结束后,局部变量将消失,但它所指向的原始对象list1将被更改:

它仍在改变

由于仍然指出list1,原始列表不会被销毁.

编辑:如果你想看看你眼前发生的所有这些事情,只需去看看这个极其神奇的模拟器:

在此输入图像描述

*如果您不知道什么是垃圾收集器......那么,您将在了解自己的问题后立即发现.

  • 还有一个好的[服务](http://people.csail.mit.edu/pgbovine/python/tutor.html#mode=edit)一步一步地去python代码并查看浏览器中的所有变量!非常接近你写的,@ brandizzi (5认同)
  • 请注意,垃圾收集器不是负责释放该列表的人.相反,列表的引用计数命中0,因此可以立即释放内存.python的垃圾收集器只在那里打破参考周期. (2认同)