正如glglgl 所提到的,这是 CPython 的一个实现细节。如果您查看Objects/longobject.c
CPython 的源代码(例如 3.3.0 版),您会找到正在发生的事情的答案:
#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
(包括)之间的数字通过small_ints
数组 in共享Objects/longobject.c
。
-edit- 我看到elssar 注意到对于一些文字的实习有类似的答案。如this answer所述,文档中PyInt_FromLong
也提到了这一事实。