我理解这里发生的事情:
>>> x = 5
>>> y = x
>>> id(x)
8729216
>>> id(y)
8729216
我也理解,对于-5到256之间的整数,Python解释器由于使用频率而提前初始化了一个整数块,所以我希望如下:
>>> x = 5
>>> y = 5
>>> id(x)
8729216
>>> id(y)
8729216
我不确定如果创建了大于256的整数会发生什么,所以我在解释器中输入了一些代码:
>>> x = 1234567890
>>> y = 1234567890
>>> id(x)
140542533943248
>>> id(y)
140542533943088
好的,id值不同,因此分配了两个不同的整数对象,它们碰巧具有相同的值。
我以为就是这样,但后来我在脚本中运行了相同的代码并且id值相同:
x = 1234567890
y = 1234567890
print(id(x))
print(id(y))
打印在屏幕上的值:
139663862951888
139663862951888
咦?这里他们引用相同的整数对象。是什么给了什么?
答案 0 :(得分:2)
我们可以反汇编字节码来检查这里发生了什么:
def func():
x = 1234567890
y = 1234567890
print(id(x))
print(id(y))
import dis
dis.dis(func)
输出结果为:
3 0 LOAD_CONST 1 (1234567890)
3 STORE_FAST 0 (x)
4 6 LOAD_CONST 1 (1234567890)
9 STORE_FAST 1 (y)
5 12 LOAD_GLOBAL 0 (id)
15 LOAD_FAST 0 (x)
18 CALL_FUNCTION 1
21 PRINT_ITEM
22 PRINT_NEWLINE
6 23 LOAD_GLOBAL 0 (id)
26 LOAD_FAST 1 (y)
29 CALL_FUNCTION 1
32 PRINT_ITEM
33 PRINT_NEWLINE
34 LOAD_CONST 0 (None)
37 RETURN_VALUE
现在我们看到有问题的实体是使用LOAD_CONST
操作码获取的。
文档并不是非常容易理解这里发生了什么,但基本上,窥孔优化器在此块之前已经看到了这个常量,因此它将返回相同的常量。显然,这仅适用于不可变的文字 - 而且它是CPython特定的优化。
另请注意,常量可以特定于单个代码对象(这是一个函数属性):
def test1():
return 1234567890
def test2():
return 1234567890
a = test1()
b = test2()
print(a is b) # False
def test3():
a = 1234567890
b = 1234567890
return a, b
t = test3()
print(t[0] is t[1]) # True
以上结果是使用python2.7.10和python3.6.0a2生成的。如果您使用pypy
运行它,则会True
打印两次。
答案 1 :(得分:1)
以下解释器示例支持@ mgilson的见解,即OP中描述的行为是CPython优化代码对象的产物:
元组分配(单一代码对象:参考优化)
>>> x, y = 1234567890, 1234567890
>>> x is y
True
复合语句(单一代码对象:参考优化)
>>> x = 1234567890; y = 1234567890
>>> x is y
True
多个语句(多个代码对象:无参考优化)
>>> x = 1234567890
>>> y = 1234567890
>>> x is y
False