python - 为什么将一个列表连接到另一个列表会在内存中创建另一个对象,而其他操作会导致突变?

标签 python

<分区>

案例 A:

list1=[0, 1, 2, 3]

list2=list1

list1=list1+[4]

print(list1)

print(list2)

输出:

[0, 1, 2, 3, 4]

[0, 1, 2, 3]

(这种非变异行为也会发生在连接多个条目的列表时,以及“乘以”列表时,例如 list1=list1*2,实际上任何类型的“重新赋值”,它使用中缀运算符对列表执行操作,然后使用“=”将该操作的结果分配给相同的列表名称

在这种情况下,list1 指向的原始列表对象在内存中没有改变,list2 仍然指向它,只是在内存中为 list1 现在指向的连接结果创建了另一个对象(现在有内存中两个截然不同的列表对象)


案例 B:

list1=[0, 1, 2, 3]

list2=list1

list1.append(4)

print(list1)

print(list2)

---

输出:

[0, 1, 2, 3, 4]

[0, 1, 2, 3, 4]

案例 C:

list1=[0, 1, 2, 3]

list2=list1

list1[-1]="foo"

print(list1)

print(list2)

输出:

[0, 1, 2, 'foo']

[0, 1, 2, 'foo']

在 B 和 C 的情况下,list1 指向的原始列表对象发生了变化,list2 仍然指向同一个对象,因此 list2 的值发生了变化。 (内存中仍然只有一个列表对象,它已经发生了变异)。

这种行为对我这个菜鸟来说似乎不一致。这有充分的理由/效用吗?

编辑:

我将列表变量名称从“list”和“list_copy”更改为“list1”和“list2”,因为这显然是一个非常糟糕且令人困惑的名称选择。

我选择了 Kabanus 的回答,因为我喜欢他指出变异操作在 Python 中总是(?)显式的方式。

事实上,可以通过将 Kabanus 的回答总结为他的两个陈述来对我的问题做一个简短的回答:

-“在 python 中,变异操作是显式的”

-“加法[或乘法]运算符[在列表对象上执行]创建一个新对象,并且不会隐式更改 x[列表对象]。”

我还可以添加:

-“每次使用方括号描述列表时,都会创建一个新的列表对象”

[这是来自:http://www-inst.eecs.berkeley.edu/~selfpace/cs9honline/Q2/mutation.html ,关于这个主题的很好的解释]

在 Kabanus 的回答之后,我还意识到在跟踪程序中的突变时必须多么小心:

l=[1,2] 
z=l 
l+=[3]
z=z+[3] 

l=[1,2] 
z=l 
z=z+[3] 
l+=[3] 

将产生完全不同的 z 值。这一定是一个常见的错误来源,不是吗?

我才刚刚开始学习,还没有深入研究 OOP 概念,但我想我已经开始理解围绕函数范式的大惊小怪是什么......

最佳答案

l += [4]

相当于:

l.append(4)

并且不会创建副本。

l = l + [4]

是对 l赋值,它首先计算赋值的右侧,然后将结果对象赋给名称 l。此操作无法改变 l

更新:我想我还没有说清楚。当然,对赋值 RHS 的操作可能涉及改变作为 LHS 当前值的对象;但最后,计算 RHS 的结果被分配给 LHS,从而覆盖了之前的任何突变。示例:

def increment_first(x):
    x[0] += 1
    return []

l = [ 1 ]
l = increment_first(l)

虽然对 increment_first 的调用会增加 l[0] 作为其副作用,但是一旦 RHS 的值(在这种情况 - 一个空列表)被分配给 l

关于python - 为什么将一个列表连接到另一个列表会在内存中创建另一个对象,而其他操作会导致突变?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45195447/

相关文章:

python - 将现有的 Python 库集成到 Anaconda

java - 将其从 Python 转换为 Java

python - Pandas 读取多个带有模式名称的 Excel 工作表

python - 42000 您的 SQL 语法有误;查看与您的 MySQL 服务器对应的手册

python - 使用python在Linux中分配特定大小的文件

python - 动态语言 IDE 中的自动完成,特别是 PyDev 中的 Python

python - 有没有办法在PyCharm控制台中查看参数信息?

python - 列表中列表的直方图

python - Tensorflow 自动编码器成本不会降低?

Python ctypes : Passed arguments are null when using restype