为什么(0-6)是-6 = False?

2022-01-14 00:00:00 python debugging integer cpython

问题描述

可能重复:
Python是"运算符对整数的行为异常

今天我尝试调试我的项目,经过几个小时的分析,我得到了这个:

Today I tried to debug my project and after a few hours of analysing I'd got this:

>>> (0-6) is -6
False

但是,

>>> (0-5) is -5
True

你能解释一下,为什么?也许这是某种错误或非常奇怪的行为.

Could you explain to me, why? Maybe this is some kind of bug or very strange behavior.

> Python 2.7.3 (default, Apr 24 2012, 00:00:54) [GCC 4.7.0 20120414 (prerelease)] on linux2
>>> type(0-6) 
<type 'int'>
>>> type(-6) 
<type 'int'>
>>> type((0-6) is -6)
<type 'bool'>
>>> 


解决方案

所有从 -5 到 256 的整数都被缓存为与 CPython 共享相同地址的全局对象,因此 is 测试通过.

All integers from -5 to 256 inclusive are cached as global objects sharing the same address with CPython, thus the is test passes.

这个神器在http://www.laurentluce中有详细解释.com/posts/python-integer-objects-implementation/,我们可以在 http://hg.python.org/cpython/file/tip/Objects/longobject.c.

This artifact is explained in detail in http://www.laurentluce.com/posts/python-integer-objects-implementation/, and we could check the current source code in http://hg.python.org/cpython/file/tip/Objects/longobject.c.

使用特定结构来引用小整数并共享它们,因此访问速度很快.它是一个包含 262 个指向整数对象的指针的数组.这些整数对象是在初始化期间在我们上面看到的整数对象块中分配的.小整数范围是 -5 到 256.许多 Python 程序花费大量时间使用该范围内的整数,因此这是一个明智的决定.

A specific structure is used to refer small integers and share them so access is fast. It is an array of 262 pointers to integer objects. Those integer objects are allocated during initialization in a block of integer objects we saw above. The small integers range is from -5 to 256. Many Python programs spend a lot of time using integers in that range so this is a smart decision.

这只是 CPython 的一个实现细节,你不应该依赖它. 例如,PyPy 实现了整数的 id 返回自身,所以 (0-6) 是 -6 始终为真,即使它们在内部是不同的对象";它还允许您配置是否启用此整数缓存,甚至设置下限和上限.但一般来说,从不同来源检索到的对象不会是相同的.如果要比较相等性,只需使用 ==.

This is only an implementation detail of CPython and you shouldn't rely on this. For instance, PyPy implemented the id of integer to return itself, so (0-6) is -6 is always true even if they are "different objects" internally; it also allows you to configure whether to enable this integer caching, and even set the lower and upper bounds. But in general, objects retrieved from different origins will not be identical. If you want to compare equality, just use ==.

相关文章