列表理解分配/比较在256之后失败

oyv*_*ind 2 python list variable-assignment

我试图找到切片分配和列表的常规分配之间的性能差异.这是代码:

import time

N =  1000  
a = list(range(N))
b = list(range(N))

time1 = time.time()
for i in range(N):
    a = [x for x in a if x is not i]
time2 = time.time()
for i in range(N):
    b[:] = [x for x in b if x is not i]
time3 = time.time()

print a
print b    
print time2 - time1
print time3 - time2
Run Code Online (Sandbox Code Playgroud)

我的期望是,每个列表ab,这一次删除一个元素,这样print aprint b两个打印空列表.相反,他们似乎总是打印起始列表,但256缺少第一个元素.

他们都打印:

[257, 258, 259 ... N-1]
Run Code Online (Sandbox Code Playgroud)

怎么了?

我正在使用Python 2.7.6.

aba*_*ert 6

问题是你用的是is代替==.

前者检查对象身份,而不是平等.没有理由相信评估,比方说,300+1两次会给你相同的int对象,只是他们都会给你int价值的对象301.

出现这种情况,为数字"工作"多达256个,因为您的特定Python实现*恰好实习生整数高达256启动时,它创造了多少单身的对象1,对于一个单独的对象2,依此类推.只要表达式求值为数字1,它就会为您提供该对象,而不是新对象.**

不用说,你不应该依赖于这种优化.


*IIRC,从1.x天到3.5的每个版本的CPython都默认为-5到256之间的所有整数的行为,但你可以在构建时更改这些限制或关闭该功能,并且可能会有不同的实现做点别的事.

**如果你想知道它在CPython中是如何工作的,那么在C API级别,PyLong_FromLong通过在单例值数组中查找从-5到256的数字来实现这一点.你可以看到3.4版本的代码,例如,这里 ; 它调用的宏CHECK_SMALL_INT和实际函数get_small_int,以及函数使用的静态数组都在同一个文件中,靠近顶部.