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

时间:2015-04-29 08:47:53

标签: 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

我的期望是,对于每个列表ab,这将一次删除一个元素,以便print aprint b都打印空列表。相反,他们似乎总是打印起始列表,但缺少第一个256元素。

他们都打印:

[257, 258, 259 ... N-1]

发生了什么事?

我使用的是Python 2.7.6。

1 个答案:

答案 0 :(得分:6)

问题是您使用的是is而不是==

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

这发生在" work"对于最大为256的数字,因为您的特定Python实现 * 最多可发生256个实习生整数。在启动时,它会为数字1创建一个单独的对象,{{1} }}, 等等。每当表达式求值为2时,它就会为您提供该对象,而不是新对象。 **

毋庸置疑,你不应该依赖这种优化。

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

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