TA的每日心情 | 开心 2019-11-20 15:00 |
---|
签到天数: 2 天 [LV.1]初来乍到
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
完全理解 Python 迭代对象、迭代器、生成器之可迭代器 r+ x" I3 I+ Z7 q; l2 q2 C' L
迭代器(iterator)
, K, U/ g* w: S0 |: g$ h# E# d" ^6 g
那么什么迭代器呢?它是一个带状态的对象,他能在你调用next()方法的时候返回容器中的下一个值,任何实现了__iter__和__next__()(python2中实现next())方法的对象都是迭代器,__iter__返回迭代器自身,__next__返回容器中的下一个值,如果容器中没有更多元素了,则抛出StopIteration异常,至于它们到底是如何实现的这并不重要。0 ]) j: o! X' Y) o1 B2 {4 E
0 t6 Y5 E C6 \+ K6 R. J
所以,迭代器就是实现了工厂模式的对象,它在你每次你询问要下一个值的时候给你返回。有很多关于迭代器的例子,比如itertools函数返回的都是迭代器对象。- y; C/ `4 n/ t
9 T/ B/ ~9 K2 D) @生成无限序列:1 b- L) q" J( G8 p, n
>>> from itertools import count
$ ~* {; G/ y% ~2 z4 X3 g. h>>> counter = count(start=13)+ H8 f* D( k' | U9 T$ N0 v, _
>>> next(counter)4 A' }/ Y! y5 O* \" C
13) r0 q; D A+ y3 c9 T" T8 ^7 x6 u
>>> next(counter)( A; w, |' [8 K6 t, Y+ B# m
14; d! I" j3 R% Z8 @( P! x8 T5 }
; @0 \0 Y% s/ b8 O8 a( U从一个有限序列中生成无限序列:7 ]1 z& C6 M Q) ^, I7 u* H
_$ b% F0 X% w) W! Q: I+ J
>>> from itertools import cycle
& X$ p" V( R: ]7 C8 l>>> colors = cycle(['red', 'white', 'blue'])
/ m! D O9 a! d1 L: Q' Z>>> next(colors)
- R+ s8 [- S0 g# p'red'
+ ?( a2 i1 X( `2 f>>> next(colors)
- M& n# c; }3 X. _: A'white'# Z2 o* P6 D1 B3 S8 o
>>> next(colors)0 U. `% Y6 Z0 J' [# D' D3 }
'blue'
, @$ y- l- o2 r5 [+ ~>>> next(colors)
& P# d2 d9 t o. d1 y2 V( y, \9 x'red'
# E% o0 y! j, i- p: ~3 `7 B. p% n: {) H- e( T
从无限的序列中生成有限序列:
5 i5 o/ y2 I& ^* @1 ]6 z>>> from itertools import islice
# C- Y" J4 P0 s) j' i. O>>> colors = cycle(['red', 'white', 'blue']) # infinite
0 ?" h* ^ _# @: b. t6 K3 i0 W>>> limited = islice(colors, 0, 4) # finite% N I l9 R: A! e# Y7 b( f0 j
>>> for x in limited:6 d; f; w; f0 O0 b* L
... print(x)8 s6 P# l8 s# k$ K2 V
red/ a- S' ?# b( B9 I; X+ W
white
9 R1 n3 M* S2 P5 Cblue4 T5 e1 d7 z8 T' W. u
red
' e8 Q, e; ~; H9 K, x4 h$ E6 p
5 I& W$ D0 m3 |5 w为了更直观地感受迭代器内部的执行过程,我们自定义一个迭代器,以斐波那契数列为例:
1 Z) p( S2 o5 B1 R% |class Fib:
! x0 O1 R, s% }6 ]+ C2 D* Mdef __init__(self):, W6 [. ]& R1 W! V- w3 b. m
self.prev = 00 Y$ ~+ f# d/ \$ k0 x
self.curr = 10 ^ \# [# t8 s6 N; R
9 x7 M7 L2 A0 _7 U# l( H0 D* D
def __iter__(self):
% l- K6 ~, j1 O; Creturn self
4 {) _8 _9 ]- z& t/ i" y- l# J$ f5 T( \
def __next__(self):
7 c @: T7 S* ]1 e6 Rvalue = self.curr
0 h$ q8 H5 s7 K8 J0 d: Xself.curr += self.prev9 \! Y) {3 r# ]+ [
self.prev = value% I6 N' d7 N6 ]% w
return value8 V) w1 c: b1 x' A
& q# ?4 @% f5 k+ R0 O; A1 M
>>> f = Fib(); g' `7 }$ v2 M V" @( z5 T
>>> list(islice(f, 0, 10))
+ c6 p. l6 d9 r[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; c" D8 [+ P! L- B8 ^
8 v+ I: J! w; c& j3 C. g
Fib既是一个可迭代对象(因为它实现了__iter__方法),又是一个迭代器(因为实现了__next__方法)。实例变量prev和curr用户维护迭代器内部的状态。每次调用next()方法的时候做两件事:
- e! b: V4 U% P- K# M0 s4 K0 m$ \0 b5 l: ~8 {) w1 r3 k) W
为下一次调用next()方法修改状态* c1 X3 f+ {1 a) R6 m0 T
为当前这次调用生成返回结果 u" X: S! G" g+ l* R/ y7 {
, x5 q9 R) [0 H8 J Y( A
迭代器就像一个懒加载的工厂,等到有人需要的时候才给它生成值返回,没调用的时候就处于休眠状态等待下一次调用。 |
! I! a' D5 e* N$ K |
|