列表理解,映射和numpy.vectorize性能

发布于 2021-01-29 15:15:33

我有一个函数foo(i),它需要一个整数,并且需要花费大量时间才能执行。下列任何一种初始化 a的 方法之间是否会有明显的性能差异:

a = [foo(i) for i in xrange(100)]

a = map(foo, range(100))

vfoo = numpy.vectorize(foo)
a = vfoo(range(100))

(我不在乎输出是列表还是numpy数组。)

有没有更好的办法?

关注者
0
被浏览
51
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    第一条评论:不要在xrange(range()样本中混合使用…这样做会使您在比较苹果和橙子时的问题无效。

    我第二个@Gabe的想法是,如果您有许多大型数据结构,则numpy应该在总体上胜出……只是要记住,大多数时候C的速度要比Python快,但是大多数时候PyPy的速度要比CPython快。
    :-)

    就listcomps与map()调用而言…一个调用101个函数,而另一个调用102个。这意味着您不会看到时间上的显着差异,如下所示,使用@Mike建议的 timeit
    模块:

    • 清单理解

    $ python -m timeit "def foo(x):pass; [foo(i) for i in range(100)]"
    1000000 loops, best of 3: 0.216 usec per loop
    $ python -m timeit "def foo(x):pass; [foo(i) for i in range(100)]"
    1000000 loops, best of 3: 0.21 usec per loop
    $ python -m timeit "def foo(x):pass; [foo(i) for i in range(100)]"
    1000000 loops, best of 3: 0.212 usec per loop

    • map() 函数调用

    $ python -m timeit "def foo(x):pass; map(foo, range(100))"
    1000000 loops, best of 3: 0.216 usec per loop
    $ python -m timeit "def foo(x):pass; map(foo, range(100))"
    1000000 loops, best of 3: 0.214 usec per loop
    $ python -m timeit "def foo(x):pass; map(foo, range(100))"
    1000000 loops, best of 3: 0.215 usec per loop

    尽管如此,除非您打算 使用
    通过这两种技术创建的列表,否则请完全避免使用它们(使用列表)。IOW,如果您要做的只是遍历它们,那么当您只关心一次查看每个元素时,只要立即丢弃该列表,就不值得消耗内存(并可能在内存中创建潜在的庞大列表)。你完成了。

    在这种情况下,我强烈建议您使用 生成器表达式,
    因为它们不会在内存中创建整个列表…这是一种更友好的内存,懒惰的迭代方式,可以循环遍历元素以处理不创建大型函数内存中的数组。最好的部分是它的语法与listcomps的语法几乎相同:

    a = (foo(i) for i in range(100))
    

    仅限2.x用户
    :沿着更多的迭代路线,将任何旧版2.x代码的所有range()调用都更改为xrange(),然后range()在移植到Python
    3xrange()替换并重命名为时切换到range()



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看