作为mentioned by glglgl,这是CPython 的一个实现细节。如果您查看 CPython 源代码(例如版本 3.3.0)中的 Objects/longobject.c,您会找到正在发生的事情的答案:
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
/* Small integers are preallocated in this array so that they
can be shared.
The integers that are preallocated are those in the range
-NSMALLNEGINTS (inclusive) to NSMALLPOSINTS (not inclusive).
*/
static PyLongObject small_ints[NSMALLNEGINTS + NSMALLPOSINTS];
这就解释了为什么在a = 1; b = 1 之后,a is b 将是True,即使你说a += 2; b +=2; a -= 2; b -= 2。每当一个数字被计算为具有适合该数组的值时,就会从该数组中简单地选取生成的对象,从而节省一点内存。
您可以使用如下函数计算出small_ints 数组的边界:
def binary_search(predicate, lo, hi):
while lo + 1 < hi:
mid = (lo + hi) / 2
if predicate(mid):
lo = mid
else:
hi = mid
return lo
def is_small_int(n):
p = n + 1
q = n + 1
return (p - 1) is (q - 1)
def min_neg_small_int():
p, q = -1, -1
if p is not q:
return 0
while p is q:
p += p
q += q
return binary_search(is_small_int, p / 2, p) - 1
def max_pos_small_int():
p, q = 1, 1
if p is not q:
return 0
while p is q:
p += p
q += q
return binary_search(is_small_int, p / 2, p)
def small_int_bounds():
return (min_neg_small_int(), max_pos_small_int())
对于我的构建(Python 2.7、64 位 Windows 构建),small_int_bounds() == (-5, 256)。这意味着-5 和256(含)之间的数字通过Objects/longobject.c 中的small_ints 数组共享。
-edit- 我看到elssar noted 有一个similar answer about interning of some literals。 in the documentation for PyInt_FromLong 也提到了这个事实,this answer 也提到了这一点。