131

可能重复:
Python“is”运算符对整数的行为异常

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

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

4 回答 4

154

从 -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整数的返回自身,所以(0-6) is -6即使它们在内部是“不同的对象”,也总是如此;它还允许您配置是否启用此整数缓存,甚至设置下限和上限。但一般来说,从不同来源检索到的对象不会是相同的。如果要比较相等性,只需使用==.

于 2012-07-13T18:29:38.370 回答
30

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

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

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

查看 CPython 源代码:)/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(包括)。

来源

于 2012-07-13T18:30:25.867 回答
27

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

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

于 2012-07-13T18:30:13.210 回答
17

这是因为 CPython 缓存了一些小整数和小字符串,并为该对象的每个实例提供了相同的id().

(0-5)-5具有相同的值,而对于和id()则不成立0-6-6

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

同样对于字符串:

>>> x = 'abc'
>>> y = 'abc'
>>> x is y
True
>>> x = 'a little big string'
>>> y = 'a little big string'
>>> x is y
False

有关字符串缓存的更多详细信息,请阅读:is运算符在将字符串与空格进行比较时表现不同

于 2012-07-13T18:31:40.067 回答