这两种方案 - lambda 和循环 - Python 有什么区别?

7 投票
4 回答
11863 浏览
提问于 2025-04-16 00:11

我想计算一个范围内所有偶数的总和。我有两个解决方案,但我不太确定每个方案的优缺点。哪个方案更好呢?

import sys
domain = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Cal1 = sum(filter(lambda n : n % 2 == 0, domain))
Cal2 = sum([n for n in domain if n % 2 == 0])
sys.stdout.write("Cal1 = {0}\n".format(Cal1))
sys.stdout.write("Cal2 = {0}\n".format(Cal2))

4 个回答

2

赞同其他很棒的回答。

额外补充:生成器表达式的速度更快...

$ python -m timeit -s 'L = xrange(10)' 'sum(filter(lambda n: n % 2 == 0, L))'
100000 loops, best of 3: 3.59 usec per loop

$ python -m timeit -s 'L = xrange(10)' 'sum(n for n in L if n % 2 == 0)'
100000 loops, best of 3: 2.82 usec per loop

关于timeit的文档

7

这里是一个稍旧的Mac笔记本上不同版本的运行速度:

$ py26 -mtimeit -s'domain = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]' 'sum(filter(lambda n : n % 2 == 0, domain))'
100000 loops, best of 3: 4.41 usec per loop
$ py26 -mtimeit -s'domain = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]' 'sum([n for n in domain if n % 2 == 0])'
100000 loops, best of 3: 2.69 usec per loop
$ py26 -mtimeit -s'domain = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]' 'sum(n for n in domain if n % 2 == 0)'
100000 loops, best of 3: 2.86 usec per loop

需要注意的是,虽然生成表达式(genexp)版本看起来更酷,但列表推导(listcomp)实际上稍微快一点(不过这个速度差别不大,除非你在优化一个非常紧凑的循环代码;-)。像往常一样,基于lambda的版本明显慢很多,正如其他人提到的那样——在Python中,lambda有点像“贫穷的亲戚”;-((不过定义的函数在这里表现也不会好太多))

13

第二种方法其实应该用生成器,而不是列表推导式,因为你并不需要创建一个列表来计算生成器的输出总和。

Cal2 = sum(n for n in domain if n % 2 == 0)

这是一种现在更受欢迎的(也就是“pythonic”)做法。

  • 使用列表推导式(就是包含[]的那种,你原来的Cal2)是不太好的选择,因为它实际上会构造一个列表对象来返回,这样会增加额外的开销。

  • 使用filter(你的Cal1)其实和生成器是一样的(没有[]的版本),但需要多打一些字,而且可读性没有直接用生成器表达式(我上面发的代码)那么好。

撰写回答