我试图找到切片分配和列表常规分配之间的性能差异。这是代码:
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
我的期望是,对于每个列表a
和b
,这将一次删除一个元素,以便print a
和print b
都打印空列表。相反,他们似乎总是打印起始列表,但缺少第一个256
元素。
他们都打印:
[257, 258, 259 ... N-1]
发生了什么事?
我使用的是Python 2.7.6。
答案 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
以及函数使用的静态数组都在同一个文件中,靠近顶部。