作为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所述。
请参阅http://stackoverflow.com/questions/306313/python-is-operator-behaves-unexpectedly-with-integers –
谢谢你们两位,我会将其标记为重复 – nvlass
我认为这个回答会有帮助 - literals from -1 to 256 and some short strings are interned – elssar