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

时间:2012-07-13 18:25:48

标签: python debugging integer cpython

  

可能重复:
  Python “is” operator behaves unexpectedly with integers

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

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

但是,

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

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

> 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'>
>>> 

4 个答案:

答案 0 :(得分:151)

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

http://www.laurentluce.com/posts/python-integer-objects-implementation/详细介绍了此工件,我们可以在http://hg.python.org/cpython/file/tip/Objects/longobject.c中查看当前的源代码。

  

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

这只是CPython的一个实现细节,你不应该依赖它。例如,PyPy实现了id整数来返回它自己,所以{ {1}}即使在内部是“不同的对象”,也总是如此;它还允许您配置是否启用此整数缓存,甚至设置下限和上限。但一般而言,从不同来源检索的对象将不相同。如果要比较相等性,只需使用(0-6) is -6

答案 1 :(得分:29)

Python在解释器中存储-5到256范围内的整数:它有一个整数对象池,从中返回这些整数。这就是为什么这些对象是相同的:(0-5)-5但不是(0-6)-6,因为它们是在现场创建的。

这是CPython源代码中的源代码:

#define NSMALLPOSINTS           257
#define NSMALLNEGINTS           5
static PyIntObject *small_ints[NSMALLNEGINTS + NSMALLPOSINTS];

view CPython source code/trunk/Objects/intobject.c)。源代码包括以下注释:

/* References to small integers are saved in this array so that they
   can be shared.
   The integers that are saved are those in the range
   -NSMALLNEGINTS (inclusive) to NSMALLPOSINTS (not inclusive).
*/

然后is运算符将它们(-5)相等,因为它们是相同的对象(相同的内存位置),但另外两个新的整数(-6)将位于不同的内存位置(然后is将不会返回True)。请注意,上述源代码中的257适用于正整数,因此为0 - 256(包括)。

source

答案 2 :(得分:26)

这不是一个错误。 is不是一个平等测试。 ==会给出预期的结果。

此行为的技术原因是Python实现可以自由地将同一常量值的不同实例视为同一对象或不同对象。您正在使用的Python实现选择使某些小常量共享同一个对象,以节省内存。您不能依赖于此版本与版本相同的版本或不同的Python实现。

答案 3 :(得分:17)

这种情况正在发生,因为CPython会缓存一些小整数和小字符串,并为该对象的每个实例提供相同的id()

(0-5)-5的{​​{1}}值相同,id()0-6不适用

-6

类似于字符串:

>>> id((0-6))
12064324
>>> id((-6))
12064276
>>> id((0-5))
10022392
>>> id((-5))
10022392

有关字符串缓存的更多详细信息,请阅读:is operator behaves differently when comparing strings with spaces