TA的每日心情 | 开心 2019-11-20 15:00 |
---|
签到天数: 2 天 [LV.1]初来乍到
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
完全理解 Python 迭代对象、迭代器、生成器之可迭代器
7 T- P" K! M- }. q迭代器(iterator)
6 h- s- w) ~& L9 P, O% {9 F9 Q% l8 p6 x5 n4 X
那么什么迭代器呢?它是一个带状态的对象,他能在你调用next()方法的时候返回容器中的下一个值,任何实现了__iter__和__next__()(python2中实现next())方法的对象都是迭代器,__iter__返回迭代器自身,__next__返回容器中的下一个值,如果容器中没有更多元素了,则抛出StopIteration异常,至于它们到底是如何实现的这并不重要。" t6 P' E0 A4 [, {- G
; ~4 d! }6 r/ l, {3 f
所以,迭代器就是实现了工厂模式的对象,它在你每次你询问要下一个值的时候给你返回。有很多关于迭代器的例子,比如itertools函数返回的都是迭代器对象。. i: y8 W' E7 [; O6 F: C
# t0 a& x0 U2 ]: a" i, }" x生成无限序列:$ p, A& e: `% }4 I+ F" q h
>>> from itertools import count
) a9 X( Y( C9 S1 \>>> counter = count(start=13)
6 S! M& z1 S4 C2 S4 P>>> next(counter)
/ y2 L% A* i( z8 b& v, C+ c* z13
1 P5 ~) r) ~6 n>>> next(counter)& c! Z) e, m1 b' F& W- [, t
14
; {) u3 J6 r: L- _; J/ P7 D" O& ~- Z6 {+ o0 ^2 |! R9 u
从一个有限序列中生成无限序列:
" e$ I# P: ~* j- E4 t" _; G {
>>> from itertools import cycle
$ @. J& m- H4 N3 Q>>> colors = cycle(['red', 'white', 'blue'])
- X% }& Z& k3 t, Z>>> next(colors)
8 Z/ P2 H: q3 S' R: z8 _'red'# h4 a" ~2 h! L9 A! l8 X4 e
>>> next(colors): `. Z" O( l% Z Y3 u5 U5 l8 F
'white'
' x% Z9 S: x: q/ l+ Q, }>>> next(colors)
8 H- @3 X# h! {'blue'
* S: E+ m, n9 A! q3 y4 B g>>> next(colors)
' F$ v! h! X0 w2 P'red'' r7 E4 T: n4 h7 t& k& \
/ l5 O u( g1 T
从无限的序列中生成有限序列:
( q$ j% j+ s. S+ C9 m0 p8 m% \>>> from itertools import islice6 K: X1 [! N1 Z6 }' |3 D
>>> colors = cycle(['red', 'white', 'blue']) # infinite! j% }$ j0 b# Q/ Q( A* V Q/ J( y
>>> limited = islice(colors, 0, 4) # finite& Q, a- v7 R* f2 `9 h
>>> for x in limited:$ e' I1 W5 `% `: p; ~% W$ v1 o* W% T8 @
... print(x)% d* [+ I) x5 \; _; W% V! E1 T+ p# r
red
7 D* p. b! {( hwhite
1 [ T: M9 |& r5 C$ o( Y8 \blue" W6 Q; U3 g) ?- P7 _
red/ G( l; F5 L" ^ K: {1 q
g3 }5 l8 G6 }$ S4 x
为了更直观地感受迭代器内部的执行过程,我们自定义一个迭代器,以斐波那契数列为例:8 a5 l$ n$ `, T8 A+ U' ~& h
class Fib:
( n; k6 R# b# O3 z" u6 Z, Pdef __init__(self): {" K" n$ h! q0 K+ b
self.prev = 0# ~; @' ~$ K) B- |
self.curr = 1
l D) B, d9 z- b/ H5 S4 \+ K) [& I! o; { W/ `+ h6 D+ O
def __iter__(self):
7 C: D) i" M; wreturn self3 e! }+ t" G, V
7 v8 B/ y& f1 J: q5 ]+ L3 S
def __next__(self):) _/ Y9 {$ l- I# h" I3 i; f
value = self.curr/ N) m3 R; v3 Z% c" \% i8 Y6 t/ S4 P
self.curr += self.prev1 J" e" D$ t; A' O* d
self.prev = value
( u0 T. X5 A5 c6 k y( Yreturn value% _8 u" r& d+ E( |
+ W. C3 C2 L' D H" m! b
>>> f = Fib()
# q, I6 s# j& R# r7 S) ]>>> list(islice(f, 0, 10))
: r2 |! i) b, A* O# Y[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
5 g: _( g0 d) q! `+ Q! s0 O: W
' B: q' w4 k5 `9 P9 FFib既是一个可迭代对象(因为它实现了__iter__方法),又是一个迭代器(因为实现了__next__方法)。实例变量prev和curr用户维护迭代器内部的状态。每次调用next()方法的时候做两件事:, g/ }# p3 H m; P$ Y
6 b, W4 j4 G+ l, l! ?为下一次调用next()方法修改状态. g3 L, n* m" b! \1 B" }- O
为当前这次调用生成返回结果$ r# h; l) f1 v* d, l J
" m2 f* s2 W" O6 h: Q
迭代器就像一个懒加载的工厂,等到有人需要的时候才给它生成值返回,没调用的时候就处于休眠状态等待下一次调用。 |
5 M) J" P& q4 d |
|