TA的每日心情 | 开心 2019-11-20 15:00 |
---|
签到天数: 2 天 [LV.1]初来乍到
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
完全理解 Python 迭代对象、迭代器、生成器之生成器 4 G2 ]2 U9 C7 _" V' z9 i
( H& R+ e& n; u8 K/ k生成器(generator)
6 k2 f! X x- q/ W6 ~8 u5 o6 k5 j2 a7 v D
生成器算得上是Python语言中最吸引人的特性之一,生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。它不需要再像上面的类一样写__iter__()和__next__()方法了,只需要一个yiled关键字。 生成器一定是迭代器(反之不成立),因此任何生成器也是以一种懒加载的模式生成值。用生成器来实现斐波那契数列的例子是:, j2 C; G" B! I' l9 j" j4 |
def fib():
# q# n- P% I6 {; mprev, curr = 0, 1
# Z0 N5 J3 F# D" e$ D- A. kwhile True:
4 ^1 b9 {2 `8 t- ]% G9 z8 Xyield curr X$ _3 I z- h! U
prev, curr = curr, curr + prev- B/ w. A9 o9 {" G* L+ h" J' T
[ W [" W4 N& i" v4 o, D>>> f = fib()
% f" _) {) U1 s6 e$ K( f7 d>>> list(islice(f, 0, 10))
! G! x9 L4 z3 B+ O: ?0 n[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]" o" b0 k5 \$ p& `
( K. E8 \% v, O& }, m9 h
fib就是一个普通的python函数,它特殊的地方在于函数体中没有return关键字,函数的返回值是一个生成器对象。当执行f=fib()返回的是一个生成器对象,此时函数体中的代码并不会执行,只有显示或隐示地调用next的时候才会真正执行里面的代码。; i, n1 G; r {' \
' ~5 P4 d$ t/ T% c+ v- i生成器在Python中是一个非常强大的编程结构,可以用更少地中间变量写流式代码,此外,相比其它容器对象它更能节省内存和CPU,当然它可以用更少的代码来实现相似的功能。现在就可以动手重构你的代码了,但凡看到类似:
) j* e$ G: L6 ^( F3 X/ T. Fdef something():2 C4 j1 L8 I* B* o
result = []( X+ S" J& {; @- e: [& M0 J. K7 k1 P
for ... in ...:$ A1 T$ A0 o: b; L( d" E( _- e
result.append(x)
7 T1 B2 y, h+ B& F( r! treturn result
, _) W" `% I1 `7 S c* l4 c9 C) s6 z
都可以用生成器函数来替换:
$ p! F6 Q2 j5 s& O; I3 |def iter_something():
) W! b5 Z7 H5 I' v9 {for ... in ...:0 x( s' i- D* O; U4 c6 i" v
yield x
6 C, A4 z4 O/ H. I8 e) {, ?: y6 Y: E0 P/ Q
生成器表达式(generator expression)
. `2 Q, e j5 {8 m- T8 i
- Z3 G2 C: @- }" m- p, s: g" g, V. ?生成器表达式是列表推倒式的生成器版本,看起来像列表推导式,但是它返回的是一个生成器对象而不是列表对象。
{0 o2 p7 u! r' Y1 |& i* _>>> a = (x*x for x in range(10))$ m! H5 l% S. _/ Q
>>> a8 @2 v& V5 R ^4 w# O" \5 A
at 0x401f08>: B4 O4 ]/ B8 H
>>> sum(a)5 W: g# A( V! u$ Q' l2 A9 a
285 | + H( L/ f& U# ~) B% G
|
|