python - 使用 Python 列表的“附加”时出现意外行为
问题描述
我试图理解python 列表的这种行为。
当我将一个空列表附加到另一个列表时,我希望新列表只包含一个空列表。但我不明白为什么它会添加意想不到的值。
main = [ [1,2,3], [4,5], [6] ]
l1 = []
l2 = []
for i in main:
for j in i:
l1.append(j)
# reseting value of l1 to empty list
l1 = []
# expected behaviour: an empty list will be added!
l2.append(l1)
print(l2)
我希望此代码能够打印
> [[], [], []]
但它给了我:
> [[4, 5], [6], []]
有人可以解释这是怎么发生的吗?
解决方案
l1 = []
并不意味着“清除此列表”。这意味着“创建一个新的空列表并让l1
名称引用该列表”。之前提到的任何对象l1
都不会被此操作修改。
此外,l2.append(l1)
并不意味着“将副本附加l1
到l2
”或“将此变量附加到l2
”。它的意思是“将此特定列表附加到l2
”。l2
接收对原始列表的引用,而不是新列表,并且对原始列表的修改将通过l2
. (它接收对列表的引用,而不是对l1
变量的引用 - 重新绑定l1
到新列表不会影响l2
。)
在外部循环的第一次迭代结束时,将一个空列表附加到l2
. 然后下一次迭代将一堆东西附加到该列表中,然后重新绑定l1
到一个新的空列表,在旧列表中留下一堆元素。同样的情况也发生在外循环的下一次和最后一次迭代中。
如果要清除列表,请使用
l1.clear()
或者
del l1[:]
而不是l1 = []
.
此外,如果要创建列表的(浅)副本,可以使用l1[:]
. 例如,附加l1
to的副本l2
:
l2.append(l1[:])`
如果您将代码更改为 clear l1
,但不将副本附加到l2
,l2
则将包含对单个列表的 3 个引用。这很少是你想要的。
推荐阅读
- android - 通过在标签中识别具有特定字符串前缀的复选框来禁用 Android 设置活动中的多个复选框项目
- javascript - 将复杂对象从 JS 发送到 SignalR 不起作用
- java - docker maven 存储库未复制到 /root/.m2
- c++ - 文件系统方法怎么可能比 Win32 慢得多?
- excel - VBA:如何与 VBA 中的图表进行交互?
- java - SpEL方法的名称我应该命名它
- c++ - 为什么指向类对象的指针的静态向量具有垃圾值?
- dns - 如何更改 SRV 记录格式
- r - 重命名时枢轴更宽
- zipkin - 使用 Zipkin 导出器的 Opentelemetry 未按预期工作。抛出 StatusRuntimeException: UNAVAILABLE: io 异常