for 循环相当高效的,因为它不会为新的L' 浪费空间,除非您当然需要保留原始列表,在这种情况下您的代码是错误的。
如果你只关心速度而不是效率,你可以从一个 numpy 数组而不是一个列表开始,因为你可以想出一个比列表操作执行得更快的操作。
如果你在乎更短,@wkl 提供的理解是要走的路。
l_prime = [-x if i%4 > 1 else x for i, x in enumerate(l)]
以下是使用timeit(标准库)计时的实现:
from timeit import timeit
import numpy as np
import itertools, operator
def samuel(l):
for i in range(len(l)):
if i % 4 > 1:
l[i] *= -1
return l
def chai(l):
return list(map(operator.mul, l, itertools.cycle([1, 1, -1, -1])))
def wkl(l):
return [-x if i % 4 > 1 else x for i, x in enumerate(l)]
def vladimir(l):
ar = np.array(l)
ar[2::4] *= -1
ar[3::4] *= -1
return ar.tolist()
# ensure all outcomes are the same
assert samuel(list(range(1000))) == chai(list(range(1000))) == wkl(list(range(1000))) == vladimir(list(range(1000)))
print('samuel: ', timeit(lambda: samuel(list(range(1000))), number=100000))
print('chai: ', timeit(lambda: chai(list(range(1000))), number=100000))
print('wkl: ', timeit(lambda: wkl(list(range(1000))), number=100000))
print('vladimir: ', timeit(lambda: vladimir(list(range(100000))), number=1000))
结果:
samuel: 6.736065300000519
chai: 3.7625152999999045
wkl: 7.069251500000064
vladimir: 6.424349999997503
numpy 解决方案将变得更快,无需列表转换,如下所述:
def vladimir_a(ar):
ar[2::4] *= -1
ar[3::4] *= -1
return ar.tolist()
ar = np.array(list(range(1000)))
print('vladimir array: ', timeit(lambda: vladimir_a(ar), number=100000))
结果:
vladimir array: 1.269356699999662
(我知道ar会被修改100,000次,但不影响性能)
编辑:实际上,这是不公平的 - 范围都在定时部分,这将是公平的(而且不是那么好)
def vladimir_a(ar):
ar[2::4] *= -1
ar[3::4] *= -1
return ar.tolist()
print('vladimir array: ', timeit(lambda: vladimir_a(np.array(range(1000))), number=100000))
结果:
vladimir array: 6.5144264999998995
所以你可能需要在你的实际用例中做一些时间来找到那里最快的。构建相同的数组 100000 次(或相同的列表)显然不是您正在做的事情,并且人们希望您在大型数据集上进行操作以提高速度甚至是一个考虑因素。