给出两个普通的python列表,newlist
和oldlist
,带有整数index
< len(oldlist)
,我想执行以下操作:
newlist.extend(oldlist[index:])
但没有创建中间列表oldlist[index:]
,或等效地
newlist.extend(oldlist[i] for i in xrange(index, len(oldlist)))
没有发电机的开销。这可能不使用C吗?
编辑:这个问题源自一些查看某些列表操作的c实现,特别是对于list.extend()
,当解释器确定它可以猜测尾部的大小被添加到列表中时,它分配头部列表的完整大小,并在生成元素时复制元素;对于其他情况,它一次分配一些元素(大约八个,如果内存服务),并一次复制几个元素。
完成分配时的具体情况似乎是python列表,以及其他一些__len__
的类型。据我所知,没有内置类型的“列表视图”可以满足这些要求。
答案 0 :(得分:10)
不要猜测,衡量
create = """
oldlist = range(5000)
newlist = range(5000, 10000)
index = 500
"""
tests = [
"newlist.extend(oldlist[index:])",
"newlist.extend(oldlist[i] for i in xrange(index, len(oldlist)))",
"newlist.extend(islice(oldlist, index, None))",
"""\
while index < len(oldlist):
newlist.append(oldlist[index])
index+=1""",
]
import timeit
for test in tests:
t = timeit.Timer(create + test, setup='from itertools import islice')
print test, min(t.repeat(number=100000))
newlist.extend(oldlist[index:]) 17.2596559525
newlist.extend(oldlist[i] for i in xrange(index, len(oldlist))) 53.5918159485
newlist.extend(islice(oldlist, index, None)) 19.6523411274
while index < len(oldlist):
newlist.append(oldlist[index])
index+=1 123.556715012
答案 1 :(得分:0)
显而易见的解决方案是:
while index < len(oldlist):
newlist.append(oldlist[index])
index += 1
但要对过早优化保持警惕,我从未遇到过这样一种情况,即这种解决方案中可读性的损失是值得的。当然,对所有选项进行基准测试,以确保您认为的解决方案更快,实际上是。
答案 2 :(得分:0)
appendnew = newlist.append
try:
while 1:
appendnew(oldlist[index])
index += 1
except IndexError:
pass
或稍微不那么令人难以置信:
appendnew = newlist.append
for i in xrange(index, len(oldlist)):
appendnew(oldlist[i])
答案 3 :(得分:0)
有关更好基准测试的一些线索
测量开销并将其减去。
将代码放在函数或方法中(模拟现实;有助于确保将变量作为全局变量不会产生令人讨厌的影响)。
from itertools import islice
def f0(newlist, oldlist, index):
pass
def f1(newlist, oldlist, index):
newlist.extend(oldlist[index:])
def f2(newlist, oldlist, index):
newlist.extend(oldlist[i] for i in xrange(index, len(oldlist)))
def f3(newlist, oldlist, index):
newlist.extend(islice(oldlist, index, None))
def f4(newlist, oldlist, index):
while index < len(oldlist):
newlist.append(oldlist[index])
index += 1
>python -mtimeit -s"old=range(1000);new=range(5000,10000);ix=500;import xtnd"; "xtnd.f4(new,old,ix)"
如果被基准测试的代码有一个变量N(在这种情况下是N = len(旧列表) - 索引),则基准测试具有多个N值。如果你期望O(N)行为,O(1)结果应该是是一个调查的原因。
同时比较具有合理预期的候选人的结果 - 应调查野生变异;它们可能是由实验错误引起的。