Ora*_*Tux 26 python reference python-internals semantics
受这个关于缓存小整数和字符串的问题的启发,我发现了以下我不理解的行为.
>>> 1000 is 10**3
False
Run Code Online (Sandbox Code Playgroud)
我以为我理解了这种行为:1000是很大的缓存.1000和10**3指向2个不同的对象.但我错了:
>>> 1000 is 1000
True
Run Code Online (Sandbox Code Playgroud)
因此,Python可能会将计算与"正常"整数区别对待.但这种假设也是不正确的:
>>> 1 is 1**2
True
Run Code Online (Sandbox Code Playgroud)
如何解释这种行为?
Mar*_*ers 42
有两个独立的事情怎么回事:Python的商店int文字(和其他文字)作为编译的字节常数和小整数对象缓存为单身.
当你1000 is 1000只运行一个这样的常量时,就会存储并重用它.你真的在看同一个对象:
>>> import dis
>>> compile('1000 is 1000', '<stdin>', 'eval').co_consts
(1000,)
>>> dis.dis(compile('1000 is 1000', '<stdin>', 'eval'))
1 0 LOAD_CONST 0 (1000)
3 LOAD_CONST 0 (1000)
6 COMPARE_OP 8 (is)
9 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
这里LOAD_CONST指的是索引0处的常量; 您可以.co_consts在字节码对象的属性中看到存储的常量.
将此与1000 is 10 ** 3案例进行比较:
>>> compile('1000 is 10**3', '<stdin>', 'eval').co_consts
(1000, 10, 3, 1000)
>>> dis.dis(compile('1000 is 10**3', '<stdin>', 'eval'))
1 0 LOAD_CONST 0 (1000)
3 LOAD_CONST 3 (1000)
6 COMPARE_OP 8 (is)
9 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
有在编译时是预先计算的常量表达式窥视孔优化,这种优化已经取代了10 ** 3用1000,但优化不重新使用预先存在的常数.结果,LOAD_CONST操作码在索引0和3处加载两个不同的整数对象,这些是两个不同的 int对象.
然后就是在小整数被实习的地方进行优化; 1在Python程序的生命周期中,只创建了一个对象副本; 这适用于-5到256之间的所有整数.
因此,对于这种1 is 1**2情况,Python内部使用int()内部缓存中的单个对象.这是一个CPython实现细节.
这个故事的寓意是,is当你真正想要按价值进行比较时,你永远不应该使用它.==始终使用整数.
| 归档时间: |
|
| 查看次数: |
1519 次 |
| 最近记录: |