消除list.extend中不需要的副本

Sin*_*ion 2 python optimization

给定两个普通的python列表,newlist并且oldlist,使用整数index< len(oldlist),我想执行以下操作:

newlist.extend(oldlist[index:])
Run Code Online (Sandbox Code Playgroud)

但没有创建中间列表oldlist[index:],或等效,

newlist.extend(oldlist[i] for i in xrange(index, len(oldlist)))
Run Code Online (Sandbox Code Playgroud)

没有发电机的开销.没有使用C可以吗?

编辑:这个问题源自一些查看某些列表操作的c实现,特别是list.extend()当解释器确定它可以猜测尾部的大小被添加到列表中时,它将该完整大小分配给头列表和在生成元素时复制元素; 对于其他情况,它一次分配一些元素(大约八个,如果内存服务),并一次复制几个元素.

完成分配的具体情况似乎是python列表,还有一些其他类型的__len__.据我所知,没有内置类型的"列表视图"可以满足这些要求.

nos*_*klo 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))
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)

  • ......清楚地表明你需要小心你所测量的东西:P现在它显示了我的期望. (2认同)