克服python中缓慢的列表创建

2024-05-23 22:07:32 发布

您现在位置:Python中文网/ 问答频道 /正文

晚上好!在

我在运行一些关于列表和列表创建与迭代器创建的测试,我遇到了一些惊人的时间差异。注意以下事项:

>>> timeit.timeit('map(lambda x: x**3, [1, 2, 3, 4, 5])')
0.4515998857965542
>>> timeit.timeit('list(map(lambda x: x**3, [1, 2, 3, 4, 5]))')
2.868906182460819

第一个测试返回的迭代器版本运行速度比转换为列表快6倍多。我基本上理解为什么会发生这种情况,但我更感兴趣的是一个解决方案。有没有人知道类似于列表的数据结构可以提供快速的创建时间?(基本上,我想知道是否有一种方法可以直接从迭代器(即map或{}函数等)转到一个没有任何重大性能损失的列表中)

为了速度我可以牺牲的东西:

  1. 添加、插入、弹出和删除元素。

  2. 元素切片。

  3. 反转列表或任何就地运算符(如sort)。

  4. 包含(in)运算符。

  5. 串联和乘法。

欢迎所有建议谢谢!在

编辑:实际上这是针对python3的。在


Tags: lambda版本元素map列表时间情况事项
3条回答

在python3.x中,^{}不创建列表,而只是一个迭代器,与python2.x不同

print(type(map(lambda x: x**3, [1, 2, 3, 4, 5])))
# <class 'map'>

要真正得到一个列表,用list函数迭代它,如下所示

^{pr2}$

所以,你真的不是在比较两个相似的东西。在

为了进一步扩展另外两个人的答案:

你对迭代器有误解。但你称之为“缓慢的创造时间”,然后你寻找一个“更快的容器”,因为你的误解。在

请注意,在python中创建list对象的速度很快:

%timeit list(range(10000))
10000 loops, best of 3: 164 µs per loop

您所体验到的缓慢是您需要执行的实际循环,计算需要进入列表的值。在

请参阅一个非常未优化的示例,它缓慢地“创建”另一个列表的新列表:

^{pr2}$

所花费的时间实际上是在循环上,这在python中是“慢”的。在

这实际上就是你在这里所做的,如果你比较一下:

def your_loop(x):
    return list(map(lambda y: y**2, x))

%timeit your_loop(x)
100 loops, best of 3: 4.5 ms per loop

但有一种方法可以加快速度:

def faster_loop(x):
    return [i**2 for i in x]


%timeit faster_loop(x)
100 loops, best of 3: 3.67 ms per loop

虽然这类功能不多。问题是:这里慢的部分是数学,而不是列表和容器。你可以用numpy来证明这一点

arr = np.array(x)

%timeit arr ** 2
100000 loops, best of 3: 7.44 µs per loop

哇哦。。。疯狂加速。在

有了基准测试——我发现我自己也经常为此感到内疚——人们经常怀疑这个系统,但他们自己却常常不够。所以,python并不是没有经过优化或“慢”,只是你做错了。不要怀疑python列表的效率。怀疑你的慢,低效的代码。你可能会更快地把它弄好。。。在

在这里,纯python**运算符似乎非常慢,因为它是一个简单的乘法运算 速度更快:

def faster_loop2(x):
    return [i * i for i in x]

%timeit faster_loop2(x)
1000 loops, best of 3: 534 µs per loop

扩展fourtheye的答案;在迭代map函数之前,不会对map函数中的表达式求值。这个例子应该很清楚:

from time import sleep

def badass_heavy_function():
    sleep(3600)

# Method call isn't evaluated
foo = map(lambda x: x(), [badass_heavy_function, badass_heavy_function])

# Methods call will be evaluated, please wait 2 hours
bar = list(map(lambda x: x(), [badass_heavy_function, badass_heavy_function]))

for _ in foo:
    # Please wait one hour
    pass

相关问题 更多 >