TA的每日心情 | 开心 2019-11-20 15:00 |
---|
签到天数: 2 天 [LV.1]初来乍到
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
完全理解 Python 迭代对象、迭代器、生成器之生成器 # Y q7 Y6 h% F' O$ M. K! M6 _! M( N
: w1 Z$ u$ P: R9 a' g ^9 P
生成器(generator)
$ Y: L9 d; Z2 A5 B: `' |# V( m5 f3 `" R. p# |7 |+ v6 n
生成器算得上是Python语言中最吸引人的特性之一,生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。它不需要再像上面的类一样写__iter__()和__next__()方法了,只需要一个yiled关键字。 生成器一定是迭代器(反之不成立),因此任何生成器也是以一种懒加载的模式生成值。用生成器来实现斐波那契数列的例子是:
k" f2 N( w- h$ ydef fib():
- z1 p: u& r0 p5 T) E zprev, curr = 0, 1
+ @. W6 o7 e4 Cwhile True:% {/ _: l: \* w* u/ L7 V- h# g2 [
yield curr
6 L6 K8 n4 |" j- Lprev, curr = curr, curr + prev- G/ |* ~% x* Q' Y+ M' |2 _' v" i% k+ j
. ~4 k8 h* p! B% O9 U>>> f = fib()
o+ \6 B9 N7 X4 a8 ^! g>>> list(islice(f, 0, 10))
+ O D/ Z" ]* ~/ U# U1 z: G- w[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
2 ^/ f5 y& E, [/ V, F/ S, C! Y! e9 p0 H3 l' `5 P% d
fib就是一个普通的python函数,它特殊的地方在于函数体中没有return关键字,函数的返回值是一个生成器对象。当执行f=fib()返回的是一个生成器对象,此时函数体中的代码并不会执行,只有显示或隐示地调用next的时候才会真正执行里面的代码。. x; [% O( t# }3 t
! ^% z& G2 T8 d! |" @生成器在Python中是一个非常强大的编程结构,可以用更少地中间变量写流式代码,此外,相比其它容器对象它更能节省内存和CPU,当然它可以用更少的代码来实现相似的功能。现在就可以动手重构你的代码了,但凡看到类似:
# x* D4 e4 e, ?def something():
& g. v! }* y' G3 w0 P$ Wresult = []
6 C" r4 }6 W. b' Gfor ... in ...:
) \9 Y0 k- V. J8 s$ _! a1 B$ Sresult.append(x)
* W& ~' v( {( i2 |" Dreturn result
- M, x$ l% t6 F/ Z7 u3 N/ D8 O9 @2 C' ^$ K+ Z# A1 C) ?5 d M
都可以用生成器函数来替换:
0 g# L4 O3 ?% k: w" Wdef iter_something():% g5 J% j- z5 Z
for ... in ...:
+ J' `, X- A7 @! D! h) c" q" Ryield x/ [7 Q: }) A8 h! q) ~( u$ T
3 t" W1 j; E4 |% J Q8 I生成器表达式(generator expression)% v, g% _' F' w8 k$ u1 K
) _4 A* \$ p7 P e! ?6 q; J
生成器表达式是列表推倒式的生成器版本,看起来像列表推导式,但是它返回的是一个生成器对象而不是列表对象。3 A E2 {$ |; g& C2 o8 `; t( S
>>> a = (x*x for x in range(10))4 M, @( t2 M. `2 L9 g0 [: @7 A& O
>>> a
$ Y1 R5 O* y x3 p( a/ rat 0x401f08>
+ d- z+ L6 b% h- f0 X: l>>> sum(a)
, f" R0 |. S% P+ p. {, h0 V285 | 3 H# Y g9 P) ]: u' a0 b
|
|