Python 解释程序和脚本之间关于引用的差异
我知道这里发生了什么,请参考:Python 解释程序和脚本之间关于引用的差异,python,Python,我知道这里发生了什么,请参考: >>> x = 5 >>> y = x >>> id(x) 8729216 >>> id(y) 8729216 我还了解到,对于-5到256之间的整数,Python解释器已经提前初始化了一个整数块,因为它们的使用频率很高,所以我预计会出现以下情况: >>> x = 5 >>> y = 5 >>> id(x) 8729216 >>
>>> 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
嗯?在这里,它们引用的是同一个整数对象。给出了什么?我们可以分解字节码来检查这里发生了什么:
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
现在我们看到所讨论的实体是使用op代码获取的
文档不太容易理解这里发生了什么,但是基本上,窥视孔优化器以前在这个块中看到过这个常量,所以它将返回相同的常量。显然,这只适用于不可变的文本——这是一个特定于CPython的优化
还请注意,常量可以特定于单个代码对象(这是函数属性):
以上结果是使用python2.7.10和python3.6.0a2生成的。如果您使用
pypy
运行它,您将得到两次True
打印。以下解释器示例支持@mgilson的见解,即OP中描述的行为是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
>>> x, y = 1234567890, 1234567890
>>> x is y
True
>>> x = 1234567890; y = 1234567890
>>> x is y
True
>>> x = 1234567890
>>> y = 1234567890
>>> x is y
False