python - 评估列表理解性能后对效率的困惑

标签 python list-comprehension

我今天对列表推导和 filter() 函数进行了一些试验,因为我很想知道如果使用其中一个,效率是否会显着提高。 结果有点令人困惑。当我过滤偶数时,列表理解比传统的嵌套结构和 filter() 函数高出约 1.5 倍(即快约 1.5 倍)。
但是当我使用一个函数来检查一个数是否为素数时,filter() 函数突然变得最快。

我在下面发布了更多详细信息,如果您想自己尝试一下,我将代码上传到了 github:https://github.com/rasbt/list_comprehension_test

我多次测试了具有不同范围最大值 n 的代码,以确保结果一致并且不受我机器上某些临时后台进程的影响。

我的问题:

  • 知道为什么过滤偶数时过滤功能这么慢吗?可能是因为 lambda 函数,还是因为我正在将生成器对象转换为列表?
  • 为什么 is_prime 函数的结果如此相似,为什么 filter 函数在这里最快?

第一部分:收集偶数


a) 循环和 else-if

even_nums = []
for i in range(1, n):
    if i % 2 == 0:
        even_nums.append(i)

b) 列表理解:

even = [i for i in range(1, n) if i % 2 == 0]

c) 过滤器()函数

even_nums = list(filter((lambda x: x%2 != 0), range(1, n)))

is_even 的结果

  • 循环和 else-if:1x(引用)
  • 列表理解:快 1.5 倍
  • filter() 函数:快 0.9 倍

第二部分:收集素数


def is_prime(num):
    """ Returns True if input integer is a prime number. """
    prime = True
    if num < 2:
        prime = False

    elif num == 2:
        prime = True
    else:
        for i in range(2, num):
            if num % i == 0:
                prime = False    
                break
    return prime

a) 循环和 else-if

primes = []
for i in range(1, n):
    if is_prime(i):
        primes.append(i)

b) 列表理解:

primes = [i for i in range(1, n) if is_prime(i)]

c) 过滤器()函数

primes = list(filter(is_prime, range(1, n)))

is_prime 的结果

  • 循环和 else-if:1x(引用)
  • 列表理解:快 0.98 倍
  • filter() 函数:快 1.13 倍

最佳答案

如果你这样实现第一个测试,结果应该和第二个测试一致:

is_even = lambda i: i % 2 == 0
even = [i for i in range(1, n) if is_even(i)]

filter 实现中,每次迭代调用一次函数(lambda),这是一个额外的步骤。这种差异在第二个测试中不存在,因为在那种情况下,两个实现都已经包含每次迭代一次的调用 (is_prime)。

至于为什么 filter 稍微快一点,我怀疑这与 filter 是原生的而不是 python 代码有关。考虑到列表理解仍然对每次迭代的 python 代码进行额外的评估:即 for 之前的 i。此评估步骤在 filter 中不是必需的,它可以直接在 native 实现中产生值。

关于python - 评估列表理解性能后对效率的困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21081995/

相关文章:

python - 没有 'for' 的列表理解

python - Pandas 测量条件为真时耗时

python - 使子进程超时

haskell - 为什么 Haskell 列表推导式不并行执行?

Python list() vs 列表理解构建速度

python - 分配列表理解、差异

python - 生成 3 个总和为 n 的数字

python - return 语句中的 Lambda 给出两个输出,但如果不使用 print 则只有一个输出

Python: "unsupported operand types for +: ' long' 和 'numpy.float64' "

python - App Engine 多个电子邮件地址返回 404