最近在知乎上有人误解了Python生成器的使用,在这里我们来统一探讨下它这么用对不对。

举一个例子,编写一个函数计算一串数字里所有偶数的个数,其实是很简单的问题,但是有些人是用生成器这么写的:

In [66]: def f1(x):
   ....:     return sum(c in '02468' for c in str(x))
   ....: 
In [68]: x = int('1234567890'*50)
In [69]: %timeit f1(x)
10000 loops, best of 5: 52.2 µs per loop

生成器这么用其实是速度最慢的一种做法,花费了52微秒。我们来看看如果我改成列表解析式会怎么样:

In [67]: def f2(x):
  ....:     return sum([c in '02468' for c in str(x)])
  ....:  
In [70]: %timeit f2(x)
10000 loops, best of 5: 40.5 µs per loop 

你看,这个加速非常地明显,仅花费了40.5微秒

而且还能进一步改进, 如果我们改变之前定义的f2,让它在列表解析式后判断数字是否为偶数,是偶数才会成为最终生成的列表中的一员,这样有另一个加速:

In [71]: def f3(x):
   ....:     return sum([True for c in str(x) if c in '02468'])
   ....: 
In [72]: %timeit f3(x)
10000 loops, best of 5: 34.9 µs per loop


34.9微秒,Perfect! 不仅如此,还能继续加速!sum对于整数有一个快速路径,但是这个快速路径只激活类型为int的变量. bool不行,因此我们把True改成1,能再加一次速!

In [73]: def f4(x):
   ....:     return sum([1 for c in str(x) if c in '02468'])
   ....: 
In [74]: %timeit f4(x)
10000 loops, best of 5: 33.3 µs per loop

​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典


声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。