>å£çµæç»çæåï¼å°±æ¯ä»ç±ãåä¹ãåå¹³ãå¿èãæ©æ
ãè¯åãä¿¡å®ã温æãèå¶ãè¿æ ·çäºï¼æ²¡æå¾æ³ç¦æ¢ãå¡å±åºç£è¶ç¨£çäººï¼æ¯å·²ç»æèä½è¿èä½çéªæ
ç§æ¬²åéå¨ååæ¶ä¸äºãæä»¬è¥æ¯é å£çµå¾çï¼å°±å½é å£çµè¡äºãä¸è¦è´ªå¾èåï¼å½¼æ¤æ¹æ°ï¼äºç¸å«å¦ã(GALATIANS 5:22-26)
#çæå¨
çæå¨ï¼è±æï¼generatorï¼æ¯ä¸ä¸ªé常迷人çä¸è¥¿ï¼ä¹å¸¸è¢«è®¤ä¸ºæ¯pythonçé«çº§ç¼ç¨æè½ãä¸è¿ï¼æä¾ç¶å¾ä¹æå¨è¿éè·è¯»è
ââå°½ç®¡ä½ å¯è½æ¯ä¸ä¸ªåå¦è
ââæ¢è®¨è¿ä¸ªè¯é¢ï¼å 为æç¸ä¿¡è¯»è
çæ¬æç¨çç®çï¼ç»éä»
ä»
å°èªå·±éå¶äºåå¦è
æ°´å¹³ï¼ä¸å®æä¸é¢ä¸ç¾çå¿ââè¦æä¸ºpython髿ãé£ä¹ï¼å¼å§äºè§£çæå¨å§ã
è¿è®°å¾ä¸èçâè¿ä»£å¨âåï¼çæå¨åè¿ä»£å¨æçä¸å®çæ¸æºå
³ç³»ãçæå¨å¿
é¡»æ¯å¯è¿ä»£çï¼è¯ç¶å®åä¸ä»
ä»
æ¯è¿ä»£å¨ï¼ä½é¤æ¤ä¹å¤ï¼å没æå¤ªå¤çå«çç¨éï¼æä»¥ï¼æä»¬å¯ä»¥æå®ç解为é常æ¹ä¾¿çèªå®ä¹è¿ä»£å¨ã
æè¿ä¸ªå
³ç³»å®å¨æè§æç¹ç³æ¶äºãç¨å®å¿èºï¼ç»§ç»é
è¯»å³æäºã
##ç®åççæå¨
>>> my_generator = (x*x for x in range(4))
è¿æ¯ä¸æ¯è·å表解æå¾ç±»ä¼¼å¢ï¼ä»ç»è§å¯ï¼å®ä¸æ¯å表ï¼å¦æè¿æ ·çå¾å°çææ¯å表ï¼
>>> my_list = [x*x for x in range(4)]
以ä¸ä¸¤çåºå«å¨äºæ¯`[]`è¿æ¯`()`ï¼è½ç¶æ¯ç»å°çå·®å«ï¼ä½æ¯ç»æå®å
¨ä¸ä¸æ ·ã
>>> dir(my_generator)
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__',
'__iter__',
'__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'gi_code', 'gi_frame', 'gi_running',
'next',
'send', 'throw']
为äºå®¹æè§å¯ï¼æå°ä¸è¿°ç»æè¿è¡äºéæ°æçãæ¯ä¸æ¯åç°äºå¨è¿ä»£å¨ä¸å¿
æçæ¹æ³`__inter__()`å`next()`ï¼è¿è¯´æå®æ¯è¿ä»£å¨ã妿æ¯è¿ä»£å¨ï¼å°±å¯ä»¥ç¨forå¾ªç¯æ¥ä¾æ¬¡è¯»åºå
¶å¼ã
>>> for i in my_generator:
... print i
...
0
1
4
9
>>> for i in my_generator:
... print i
...
å½ç¬¬ä¸é循ç¯çæ¶åï¼å°my_generatoréé¢çå¼ä¾æ¬¡è¯»åºå¹¶æå°ï¼ä½æ¯ï¼å½åè¯»ä¸æ¬¡çæ¶åï¼å°±åç°æ²¡æä»»ä½ç»æãè¿ç§ç¹æ§ä¹æ£æ¯è¿ä»£å¨æå
·æçã
妿坹é£ä¸ªå表ï¼å°±ä¸ä¸æ ·äºï¼
>>> for i in my_list:
... print i
...
0
1
4
9
>>> for i in my_list:
... print i
...
0
1
4
9
é¾éçæå¨å°±æ¯æå表解æä¸ç`[]`æ¢æ`()`å°±è¡äºåï¼è¿ä»
ä»
æ¯çæå¨çä¸ç§è¡¨ç°å½¢å¼åä½¿ç¨æ¹æ³ç½¢äºï¼ä»¿ç
§å表解æå¼çå½åï¼å¯ä»¥ç§°ä¹ä¸ºâçæå¨è§£æå¼âï¼æè
ï¼çæå¨æ¨å¯¼å¼ãçæå¨è¡¨è¾¾å¼ï¼ã
çæå¨è§£æå¼æ¯æå¾å¤ç¨éçï¼å¨ä¸å°å°æ¹æ¿ä»£åè¡¨ï¼æ¯ä¸ä¸ªä¸éçéæ©ãç¹å«æ¯é对大éå¼çæ¶åï¼å¦ä¸èæè¯´çï¼å表å å
åè¾å¤ï¼è¿ä»£å¨ï¼çæå¨æ¯è¿ä»£å¨ï¼çä¼å¿å°±å¨äºå°å å
åï¼å æ¤æ éå°çæå¨ï¼æè
说æ¯è¿ä»£å¨ï¼å®ä¾å为ä¸ä¸ªå表ï¼ç´æ¥å¯¹å
¶è¿è¡æä½ï¼æ¹æ¾ç¤ºåºå
¶è¿ä»£çä¼å¿ãæ¯å¦ï¼
>>> sum(i*i for i in range(10))
285
请读è
注æè§å¯ä¸é¢ç`sum()`è¿ç®ï¼ä¸è¦ä»¥ä¸ºéé¢å°äºä¸ä¸ªæ¬å·ï¼å°±æ¯è¿ä¹åãæ¯ä¸æ¯å¾è¿·äººï¼å¦æå表ï¼ä½ ä¸å¾ä¸ï¼
>>> sum([i*i for i in range(10)])
285
éè¿çæå¨è§£æå¼å¾å°ççæå¨ï¼æ©çäºçæå¨çä¸äºç»èï¼å¹¶ä¸éç¨é¢å乿éãä¸é¢å°±è¦åæçæå¨çå
é¨ï¼æ·±å
¥çè§£è¿ä¸ªéæ³å·¥å
·ã
##å®ä¹åæ§è¡è¿ç¨
yieldè¿ä¸ªè¯å¨æ±è¯ä¸æâç产ãåºäº§â乿ï¼å¨pythonä¸ï¼å®ä½ä¸ºä¸ä¸ªå
³é®è¯ï¼ä½ å¨åéã彿°ãç±»çåç§°ä¸å°±ä¸è½ç¨è¿ä¸ªäºï¼ï¼æ¯çæå¨çæ å¿ã
>>> def g():
... yield 0
... yield 1
... yield 2
...
>>> g
建ç«äºä¸ä¸ªé常ç®åç彿°ï¼è·ä»¥å¾çå°ç彿°å¯ä¸ä¸åçå°æ¹æ¯ç¨äºä¸ä¸ªyieldè¯å¥ãç¶åè¿è¡ä¸é¢çæä½ï¼
>>> ge = g()
>>> ge
>>> type(ge)
ä¸é¢å»ºç«ç彿°è¿å弿¯ä¸ä¸ªçæå¨(generator)ç±»åç对象ã
>>> dir(ge)
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'gi_code', 'gi_frame', 'gi_running', 'next', 'send', 'throw']
å¨è¿éçå°äº`__iter__()`å`next()`ï¼è¯´æå®æ¯è¿ä»£å¨ãæ¢ç¶å¦æ¤ï¼å½ç¶å¯ä»¥ï¼
>>> ge.next()
0
>>> ge.next()
1
>>> ge.next()
2
>>> ge.next()
Traceback (most recent call last):
File "", line 1, in
StopIteration
ä»è¿ä¸ªç®åä¾åä¸å¯ä»¥çåºï¼é£ä¸ªå«æyieldå
³é®è¯ç彿°è¿å弿¯ä¸ä¸ªçæå¨ç±»åç对象ï¼è¿ä¸ªçæå¨å¯¹è±¡å°±æ¯è¿ä»£å¨ã
æä»¬æå«æyieldè¯å¥ç彿°ç§°ä½çæå¨ãçæå¨æ¯ä¸ç§ç¨æ®é彿°è¯æ³å®ä¹çè¿ä»£å¨ãéè¿ä¸é¢çä¾åå¯ä»¥çåºï¼è¿ä¸ªçæå¨ï¼ä¹æ¯è¿ä»£å¨ï¼ï¼å¨å®ä¹è¿ç¨ä¸å¹¶æ²¡æåä¸èè¿ä»£å¨é£æ ·å`__inter__()`å`next()`ï¼èæ¯åªè¦ç¨äºyieldè¯å¥ï¼é£ä¸ªæ®é彿°å°±ç¥å¥è¬å°æä¸ºäºçæå¨ï¼ä¹å°±å
·å¤äºè¿ä»£å¨çåè½ç¹æ§ã
yieldè¯å¥çä½ç¨ï¼å°±æ¯å¨è°ç¨çæ¶åè¿åç¸åºçå¼ã详ç»åæä¸ä¸ä¸é¢çè¿è¡è¿ç¨ï¼
1. `ge = g()`ï¼é¤äºè¿åçæå¨ä¹å¤ï¼ä»ä¹ä¹æ²¡ææä½ï¼ä»»ä½å¼ä¹æ²¡æè¢«è¿åã
2. `ge.next()`ï¼ç´å°è¿æ¶åï¼çæå¨æå¼å§æ§è¡ï¼éå°äºç¬¬ä¸ä¸ªyieldè¯å¥ï¼å°å¼è¿åï¼å¹¶æåæ§è¡ï¼æçç§°ä¹ä¸ºæèµ·ï¼ã
3. `ge.next()`ï¼ä»ä¸æ¬¡æåçä½ç½®å¼å§ï¼ç»§ç»å䏿§è¡ï¼éå°yieldè¯å¥ï¼å°å¼è¿åï¼åæåã
4. `gen.next()`ï¼éå¤ä¸é¢çæä½ã
5. `gene.next()`ï¼ä»ä¸é¢çæèµ·ä½ç½®å¼å§ï¼ä½æ¯å颿²¡æå¯æ§è¡çäºï¼äºæ¯`next()`ååºå¼å¸¸ã
ä»ä¸é¢çæ§è¡è¿ç¨ä¸ï¼åç°yieldé¤äºä½ä¸ºçæå¨çæ å¿ä¹å¤ï¼è¿æä¸ä¸ªåè½å°±æ¯è¿åå¼ãé£ä¹å®è·returnè¿ä¸ªè¿å弿ä»ä¹åºå«å¢ï¼
##yield
为äºå¼æ¸
æ¥yieldåreturnçåºå«ï¼æä»¬å两个没æä»ä¹ç¨éç彿°ï¼
>>> def r_return(n):
... print "You taked me."
... while n > 0:
... print "before return"
... return n
... n -= 1
... print "after return"
...
>>> rr = r_return(3)
You taked me.
before return
>>> rr
3
ä»å½æ°è¢«è°ç¨çè¿ç¨å¯ä»¥æ¸
æ°çåºï¼`rr = r_return(3)`ï¼å½æ°ä½å
çè¯å¥å°±å¼å§æ§è¡äºï¼éå°returnï¼å°å¼è¿åï¼ç¶åå°±ç»æå½æ°ä½å
çæ§è¡ãæä»¥returnåé¢çè¯å¥æ ¹æ¬æ²¡ææ§è¡ãè¿æ¯returnçç¹ç¹ï¼å
³äºæ¤ç¹ç¹ç详ç»è¯´æè¯·é
读[ã彿°(2)ãä¸çè¿åå¼ç¸å
³å
容](./202)ã
ä¸é¢å°returnæ¹ä¸ºyieldï¼
>>> def y_yield(n):
... print "You taked me."
... while n > 0:
... print "before yield"
... yield n
... n -= 1
... print "after yield"
...
>>> yy = y_yield(3) #æ²¡ææ§è¡å½æ°ä½å
è¯å¥
>>> yy.next() #å¼å§æ§è¡
You taked me.
before yield
3 #éå°yieldï¼è¿åå¼ï¼å¹¶æå
>>> yy.next() #ä»ä¸æ¬¡æåä½ç½®å¼å§ç»§ç»æ§è¡
after yield
before yield
2 #åéå°yieldï¼è¿åå¼ï¼å¹¶æå
>>> yy.next() #éå¤ä¸è¿°è¿ç¨
after yield
before yield
1
>>> yy.next()
after yield #æ²¡ææ»¡è¶³æ¡ä»¶çå¼ï¼æåºå¼å¸¸
Traceback (most recent call last):
File "", line 1, in
StopIteration
ç»å注éååé¢å¯¹æ§è¡è¿ç¨çåæï¼è¯»è
ä¸å®è½çè§£yieldçç¹ç¹äºï¼ä¹æ·±ç¥ä¸returnçåºå«äºã
ä¸è¬ç彿°ï¼é½æ¯æ¢äºreturnãä½ä¸ºçæå¨ç彿°ï¼ç±äºæäºyieldï¼åä¼éå°å®æèµ·ï¼å¦æè¿æreturnï¼éå°å®å°±ç´æ¥æåºSoptIterationå¼å¸¸è䏿¢è¿ä»£ã
ææ³¢é£å¥æ°åå·²ç»æ¯èç¸è¯äºãä¸è®ºæ¯å¾ªç¯ãè¿ä»£é½ç¨å®ä¸¾ä¾è¿ï¼ç°å¨è®©æä»¬è¿ç¨å®å§ï¼åªä¸è¿æ¯è¦ç¨ä¸yieldï¼
#!/usr/bin/env python
# coding=utf-8
def fibs(max):
"""
ææ³¢é£å¥æ°åççæå¨
"""
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
if __name__ == "__main__":
f = fibs(10)
for i in f:
print i ,
è¿è¡ç»æå¦ä¸ï¼
$ python 21501.py
1 1 2 3 5 8 13 21 34 55
ç¨çæå¨æ¹å¼å®ç°çææ³¢é£å¥æ°åæ¯ä¸æ¯è·ä»¥åçææä¸åäºå¢ï¼è¯»è
å¯ä»¥å°æ¬æç¨ä¸å·²ç»æ¼ç¤ºè¿çææ³¢é£å¥æ°åå®ç°æ¹å¼åä¸ä¸å¯¹æ¯ï¼ä½ä¼åç§æ¹æ³çå·®å¼ã
ç»è¿ä¸é¢çåç§ä¾åï¼å·²ç»æç¡®ï¼ä¸ä¸ªå½æ°ä¸ï¼åªè¦å
å«äºyieldè¯å¥ï¼å®å°±æ¯çæå¨ï¼ä¹æ¯è¿ä»£å¨ãè¿ç§æ¹å¼æ¾ç¶æ¯åé¢åè¿ä»£å¨çç±»è¦ç®ä¾¿å¤äºãä½ï¼å¹¶ä¸æå³çä¸èç就被æå¼ãæ¯çæå¨è¿æ¯è¿ä»£å¨ï¼é½æ¯æ ¹æ®å
·ä½çä½¿ç¨æ
æ¯èå®ã
##çæå¨æ¹æ³
å¨python2.5以åï¼çæå¨æäºä¸ä¸ªæ°ç¹å¾ï¼å°±æ¯å¨å¼å§è¿è¡åè½å¤ä¸ºçæå¨æä¾æ°çå¼ãè¿å°±å¥½ä¼¼çæå¨åâå¤çâä¹é´è¿è¡æ°æ®äº¤æµã
>>> def repeater(n):
... while True:
... n = (yield n)
...
>>> r = repeater(4)
>>> r.next()
4
>>> r.send("hello")
'hello'
彿§è¡å°`r.next()`çæ¶åï¼çæå¨å¼å§æ§è¡ï¼å¨å
é¨éå°äº`yield n`æèµ·ã注æå¨çæå¨å½æ°ä¸ï¼`n = (yield n)`ä¸ç`yield n`æ¯ä¸ä¸ªè¡¨è¾¾å¼ï¼å¹¶å°ç»æèµå¼ç»nï¼è½ç¶ä¸ä¸¥æ ¼è¦æ±å®å¿
é¡»ç¨åæ¬å·å
裹ï¼ä½æ¯ä¸è¬æ
åµé½è¿ä¹åï¼è¯·è¯»è
ä¹è¿½éè¿ä¸ªä¹ æ¯ã
彿§è¡`r.send("hello")`çæ¶åï¼åæ¥å·²ç»è¢«æèµ·ççæå¨ï¼å½æ°ï¼å被å¤éï¼å¼å§æ§è¡`n = (yield n)`ï¼ä¹å°±æ¯è®²send()æ¹æ³åéçå¼è¿åãè¿å°±æ¯å¨è¿è¡åè½å¤ä¸ºçæå¨æä¾å¼çå«ä¹ã
妿æ¥ä¸æ¥åæ§è¡`r.next()`ä¼ææ ·ï¼
>>> r.next()
ä»ä¹ä¹æ²¡æï¼å
¶å®å°±æ¯è¿åäºNoneãæç
§åé¢çåè¿°ï¼è¯»è
å¯ä»¥çå°ï¼è¿æ¬¡æ§è¡`r.next()`ï¼ç±äºæ²¡æä¼ å
¥ä»»ä½å¼ï¼yieldè¿åçå°±åªè½æ¯None.
è¿è¦æ³¨æï¼send()æ¹æ³å¿
é¡»å¨çæå¨è¿è¡åå¹¶æèµ·æè½ä½¿ç¨ï¼ä¹å°±æ¯yieldè³å°è¢«æ§è¡ä¸æ¬¡ã妿䏿¯è¿æ ·ï¼
>>> s = repeater(5)
>>> s.send("how")
Traceback (most recent call last):
File "", line 1, in
TypeError: can't send non-None value to a just-started generator
å°±æ¥éäºã使¯ï¼å¯å°åæ°è®¾ä¸ºNoneï¼
>>> s.send(None)
5
è¿æ¯è¿åçæ¯è°ç¨å½æ°çæ¶ä¼ å
¥çå¼ã
æ¤å¤ï¼è¿æä¸¤ä¸ªæ¹æ³ï¼close()åthrow()
- throw(type, value=None, traceback=None):ç¨äºå¨çæå¨å
é¨ï¼çæå¨çå½åæèµ·å¤ï¼ææªå¯å¨æ¶å¨å®ä¹å¤ï¼æåºä¸ä¸ªå¼å¸¸ï¼å¨yield表达å¼ä¸ï¼ã
- close()ï¼è°ç¨æ¶ä¸ç¨åæ°ï¼ç¨äºå
³éçæå¨ã
æåä¸å¥ï¼ä½ å¨ç¼ç¨ä¸ï¼ä¸ç¨çæå¨ä¹å¯ä»¥ã
------
[æ»ç®å½](./index.md) | [ä¸èï¼è¿ä»£å¨](./214.md) | [ä¸èï¼ä¸ä¸æç®¡çå¨](./235.md)
å¦æä½ è®¤ä¸ºæå¿
è¦æèµæï¼è¯·éè¿æ¯ä»å®ï¼**[email protected]**,ä¸èææ¿ã