Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python列表赋值中的语法差异导致隐式变量替换_Python_List_Variable Assignment - Fatal编程技术网

Python列表赋值中的语法差异导致隐式变量替换

Python列表赋值中的语法差异导致隐式变量替换,python,list,variable-assignment,Python,List,Variable Assignment,新手问题在这里。我很困惑,为什么只有在某些语法下,当一个列表被分配到的另一个列表被更新时,它才会自动更新。比如说, 如果我们将“a”分配给“b”并更新“b”,则“a”不受影响: >>> b = [1,1,0] >>> a = b a = [1,1,0] >>> b = [0,0,0] a = [1,1,0] 但是,如果我们将最后一个更新命令重新编写为: >>> b[:2] = [0]*2 a = [0,0,0] 为什么

新手问题在这里。我很困惑,为什么只有在某些语法下,当一个列表被分配到的另一个列表被更新时,它才会自动更新。比如说,

如果我们将“a”分配给“b”并更新“b”,则“a”不受影响:

>>> b = [1,1,0]
>>> a = b
a = [1,1,0]
>>> b = [0,0,0]
a = [1,1,0]
但是,如果我们将最后一个更新命令重新编写为:

>>> b[:2] = [0]*2
a = [0,0,0] 
为什么会这样?

因为a和b是对对象的引用。当你写作时:

a = b
b[:2] = [0, 0] # [0] * 2
b = [0,0,0]
然后a和b引用同一个对象,因此当您修改它时,作用于b,a也将更改。如果他们把指针放在哪里,在引擎盖下面,他们就指向同一个物体

当你写作时:

a = b
b[:2] = [0, 0] # [0] * 2
b = [0,0,0]
您正在修改列表,因此更改将反映在a中

相反,当你写作时:

a = b
b[:2] = [0, 0] # [0] * 2
b = [0,0,0]

b将引用一个新的、不同的列表,更改不会反映ina。

当您执行简单赋值(如b=[0,0,0])时,您正在内存中创建一个新的列表对象,并将b更改为指向该新列表对象。这与a没有关系,a可能指向其他位置,包括b过去指向的位置,这里就是这样

当您分配给像b[:2]=[0]*2这样的切片时,您正在进行就地修改,因此可以通过指向b列表的任何指针看到更改。在这种情况下,这也意味着a

例如,考虑对第一个片段的轻微修改:

>>> b = [1,1,0]
>>> a = b
>>> b[:] = [0,0,0]
>>> 
>>> a
[0, 0, 0]
>>> b
[0, 0, 0]

请注意,现在a和b显示为已修改,因为分配给b[:]会修改b所指向的列表,并且由于a指向同一列表,我们也可以通过a看到更改。同样,这与您的第一个代码段形成了对比,其中b被重定向到一个新的对象。

很有意义。后续问题:将b重新分配给[0,0,0]后,存储包含[1,1,0]的对象的内存会发生什么变化?在这一点上,它是干净的、可重用的吗?@user1211129这更像是一个实现细节。在CPython中,是的,它将被释放并可重用。@StefanoSanfilippo:CPython除了周期性运行的可选GC之外,还使用引用计数,并且实际上会立即清理没有引用的对象。另一个问题:如果我将列表设为“b”,但想复制该列表的“a”。如果“b”进行了进一步的操作,如何保存副本?@user1211129要复制列表,只需使用b=lista即可。