>>> a=1
>>> b=1
>>> id(a)
140472563599848
>>> id(b)
140472563599848
>>> x=()
>>> y=()
>>> id(x)
4298207312
>>> id(y)
4298207312
>>> x1=(1)
>>> x2=(1)
>>> id(x1)
140472563599848
>>> id(x2)
140472563599848
到目前为止,我一直认为不可变对象只有一份副本,并且将由所有变量共享(指向)。
但是当我尝试时,以下步骤我明白我错了。
>>> x1=(1,5)
>>> y1=(1,5)
>>> id(x1)
4299267248
>>> id(y1)
4299267320
任何人都可以向我解释一下内部原理吗?
>>> x1=(1)
>>> x2=(1)
实际上与
相同>>> x1=1
>>> x2=1
在 Python 中,较小的数字会在内部缓存。所以它们不会在内存中被多次创建。这就是为什么
id
和 x1
的 x2
到目前为止是相同的。
单元素元组末尾应有一个逗号,如下所示
>>> x1=(1,)
>>> x2=(1,)
执行此操作时,将构造两个新元组,其中仅包含一个元素。尽管元组内的元素相同,但它们都是不同的元组。这就是为什么他们都有不同的
id
。
让我们以最后一个示例为例并反汇编代码。
compiled_code = compile("x1 = (1, 5); y1 = (1, 5)", "string", "exec")
现在,
import dis
dis.dis(compiled_code)
会产生这样的东西
1 0 LOAD_CONST 3 ((1, 5))
3 STORE_NAME 0 (x1)
6 LOAD_CONST 4 ((1, 5))
9 STORE_NAME 1 (y1)
12 LOAD_CONST 2 (None)
15 RETURN_VALUE
它加载一个常量值,由索引
3
引用,即 (1, 5)
,然后将其存储在 x1
中。同样,它在索引 4
处加载另一个常量值并将其存储在 y1
中。如果我们查看代码对象中的常量列表,
print(compiled_code.co_consts)
会给
(1, 5, None, (1, 5), (1, 5))
3
和4
位置的元素是我们在实际代码中创建的元组。因此,Python 不会为每个不可变对象仅创建一个实例,always。这是一个我们不必太担心的实现细节。
注意:如果你只想拥有一个不可变对象的实例,你可以像这样手动完成
x1 = (1, 5)
x2 = x1
现在,
x2
和x1
都将引用同一个元组对象。
从 Python3.7 开始,元组创建使用 interning。
t1 = (1, 2, 3)
t2 = (1, 2, 3)
print(t2 is t1)
对于 Python 3.7 及以上版本,上面的代码打印
True
。