TA的每日心情 | 开心 2019-11-20 15:00 |
---|
签到天数: 2 天 [LV.1]初来乍到
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
完全理解 Python 迭代对象、迭代器、生成器之生成器 2 x& c3 H$ S; X' ^! t6 [& N5 h6 e5 R
1 `2 D# A& V6 Y `- c+ b% \' q
生成器(generator)
9 r! H' H g* D+ v" W1 }. E9 n. }+ r& K; g" H4 w. S* D
生成器算得上是Python语言中最吸引人的特性之一,生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。它不需要再像上面的类一样写__iter__()和__next__()方法了,只需要一个yiled关键字。 生成器一定是迭代器(反之不成立),因此任何生成器也是以一种懒加载的模式生成值。用生成器来实现斐波那契数列的例子是:
! L7 C& u3 l+ h% g) V0 Jdef fib():
9 Y( ~3 C- ?6 Q: B5 Y. uprev, curr = 0, 1
1 r% c" O. W# a+ ~2 U' _while True:
$ r7 |- o0 q. H: n+ vyield curr
8 a- ~ P: E0 T' z# L3 d/ u: fprev, curr = curr, curr + prev4 R8 C2 ^. D5 K. G$ j3 ` O" ~
" Q* P4 P0 G* x \6 |, d
>>> f = fib()) n' T7 n2 S* W# q$ C
>>> list(islice(f, 0, 10))3 P! l( G% H7 ^; b& d! Z3 d( Z
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]7 M+ d0 q& C* F" \
" O% f8 |# R6 {, Y8 i6 Ofib就是一个普通的python函数,它特殊的地方在于函数体中没有return关键字,函数的返回值是一个生成器对象。当执行f=fib()返回的是一个生成器对象,此时函数体中的代码并不会执行,只有显示或隐示地调用next的时候才会真正执行里面的代码。& A* @+ x5 b0 A, d4 Q3 L
. Y: c; Q5 i2 v2 U' Y: a/ k1 t
生成器在Python中是一个非常强大的编程结构,可以用更少地中间变量写流式代码,此外,相比其它容器对象它更能节省内存和CPU,当然它可以用更少的代码来实现相似的功能。现在就可以动手重构你的代码了,但凡看到类似:
7 h3 \4 X3 [1 adef something():8 S4 l% t' J* t. ?! H8 Y* b" j
result = []
- C8 D: F$ D% A; j. q( Jfor ... in ...:
* r1 y3 e- T& B; oresult.append(x)
& e3 Y! w/ B# c8 T; [return result
& v1 l7 g1 A! c7 i& H! c# S2 }# d6 q% s
都可以用生成器函数来替换:! c, r& I% U, p5 q0 P. h) Z
def iter_something():4 ?4 X2 |2 o; R# Z0 |
for ... in ...:* B7 |3 E5 W; G3 }6 P t8 c
yield x( t* N8 u( r7 e; A. I
+ x, i$ ~( ^1 g9 l) r% M
生成器表达式(generator expression)
' n4 g; i+ {+ G: C2 j$ Z0 M5 x) b( M: U+ f/ o, N
生成器表达式是列表推倒式的生成器版本,看起来像列表推导式,但是它返回的是一个生成器对象而不是列表对象。
/ m+ F" q8 ?7 k" z3 X7 ~>>> a = (x*x for x in range(10))# |, \( {" u4 W6 S8 W/ c0 g" j4 y
>>> a5 [" `6 O0 ~! B: E- N: E9 K% S
at 0x401f08>4 q, L& z4 G; ^ A+ k
>>> sum(a)
B) E8 e; z3 K9 M5 n+ V: E6 p285 |
# V0 m5 _/ `5 E3 s' n' r) X |
|