最近在知乎上有人误解了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实用宝典