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

Dmi*_*kin 129 python debugging integer cpython

可能重复:
Python"is"运算符使用整数意外运行

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

>>> (0-6) is -6
False
Run Code Online (Sandbox Code Playgroud)

但,

>>> (0-5) is -5
True
Run Code Online (Sandbox Code Playgroud)

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

> 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'>
>>> 
Run Code Online (Sandbox Code Playgroud)

ken*_*ytm 151

从-5到256(包括-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即使它们是内部的"不同对象"也总是如此; 它还允许您配置是否启用此整数缓存,甚至设置下限和上限.但一般而言,从不同来源检索的对象将不相同.如果要比较相等,请使用==.

  • @kirelagin也许这是有意的.在python中,`range(m,n)`表示[m,n)的整数区间,即m,m + 1,m + 2,...,n - 1.它不包括n,所以`range (-5,257)`不包含257,并且所描述的行为对于此范围是正确的. (3认同)
  • 这就是我要说的,但我无法正确地说出来.+1 (2认同)

Sim*_*ser 29

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

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

#define NSMALLPOSINTS           257
#define NSMALLNEGINTS           5
static PyIntObject *small_ints[NSMALLNEGINTS + NSMALLPOSINTS];
Run Code Online (Sandbox Code Playgroud)

(查看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).
*/
Run Code Online (Sandbox Code Playgroud)

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

(来源)


Rus*_*ove 26

这不是一个错误.is不是一个平等的考验.==会给出预期的结果.

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

  • >`is`不是一个平等测试.这个.`is`是一个身份测试,看两个对象是否完全相同.恰好在CPython实现中,一些int对象被缓存. (2认同)

Ash*_*ary 17

它正在发生,因为CPython缓存了一些小整数和小字符串,并给出了该对象的每个实例id().

(0-5)并且-5具有相同的值id(),这对于0-6和不适用-6

>>> id((0-6))
12064324
>>> id((-6))
12064276
>>> id((0-5))
10022392
>>> id((-5))
10022392
Run Code Online (Sandbox Code Playgroud)

对于字符串类似:

>>> x = 'abc'
>>> y = 'abc'
>>> x is y
True
>>> x = 'a little big string'
>>> y = 'a little big string'
>>> x is y
False
Run Code Online (Sandbox Code Playgroud)

有关字符串缓存的更多详细信息,请参阅:is运算符在使用空格比较字符串时的行为方式不同

  • 那么为什么`-6`被认为是"大"而'-5'不是?某些东西被认为是"大"的资格标准是什么? (2认同)