在 Fluent Python,作者 Luciano Ramalho,第 8 章,默认情况下副本是浅的,有一个示例:
>>> listOne = [3, [55, 44], (7, 8, 9)]
>>> listTwo = list(listOne)
>>> listTwo
[3, [55, 44], (7, 8, 9)]
>>> listTwo == listOne
True
>>> listTwo is listOne
False
作者建议我们应该使用 Online Python Tutor 运行这段代码,一步步看看发生了什么。
我使用 Online Python Tutor 执行了前两行,这是我得到的屏幕截图:
令我困惑的是:
每个列表中的所有三个元素,不可变整数,列表和元组实际上是相同的,例如
listOne[0] is listTwo[0] #True
listOne[1] is listTwo[1] #True
listOne[2] is listTwo[2] #True
那么为什么图表在各自列表的开头显示两个单独的 3?
Python 中的变量并不直接保存它们的值,而是对值的内存位置的引用。因此,引用“int”类型的值也是正确的。您可以使用 memory_grap 来做到这一点:
import memory_graph
memory_graph.config.no_reference_types.pop(int, None) # show references to ints
listOne = [3, [55, 44], (7, 8, 9)]
listTwo = list(listOne) # shallow copy
memory_graph.d()
但是,“int”是一种不可变类型,这意味着该类型的值在更改时会自动复制,因此,当您不绘制(或考虑)对不可变类型的引用时,不会出现任何问题。想想“写入时复制”,如果您更改
listOne
中与 listTwo
共享的“int”,它将首先被复制,因此 listTwo
不会受到更改的影响。不必要时不绘制参考会使图表(和您的心智模型)更加简单,因此通常这是首选:
import memory_graph
listOne = [3, [55, 44], (7, 8, 9)]
listTwo = list(listOne) # shallow copy
memory_graph.d()
完全披露:我是memory_graph的开发者。
这是 CPython 优化。这可能不会出现在其他 Python 实现中。
x = 256
x is 256 # True
x = 257
x is 257 # False