为什么在线Python导师将这个不可变整数以图形方式呈现为两个不同的整数?

问题描述 投票:0回答:3

在 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 copy immutable-collections
3个回答
3
投票

OnlinePythonTutor 的开发人员做出了这个决定,记录在不支持的功能下,因为这不是一个有保证的语言功能,而是特定于实现的:

Python

对于字符串和数字,你不能依赖于

id()
is
与您计算机上的 CPython 相匹配;在教导初学者时, 你不应该依赖这些行为,因为它们是 特定于实现的优化。有关详细信息,请参阅 GitHub 问题 这里和这里和这里

您可以从 issue 255 看到,对于整数,即使在 -5 到 256 范围之外,过去的行为也有所不同。


0
投票

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的开发者。


-3
投票

这是 CPython 优化。这可能不会出现在其他 Python 实现中。

x = 256
x is 256 # True
x = 257
x is 257 # False
© www.soinside.com 2019 - 2024. All rights reserved.