自從python2.2提供了yield關鍵字之后,python的生成器的很大一部分用途就是可以用來構建協同程序,能夠將函數掛起返回中間值并能從上次離開的地方繼續執行。python2.5的時候,這種生成器更加接近完全的協程,因為提供了將值和異常傳遞回到一個繼續執行的函數中,當等待生成器的時候,生成器能返回控制。
python提供的生成器設施:
- yield:能夠將自己掛起,并提供一個返回值給等待方
- send:喚起一個被掛起的生成器,并能夠傳遞一個參數,可以在生成器中拋出異常
- next:本質上相當于send(None),對每個生成器的第一次調用必須不能傳遞參數
- close:主動退出一個生成器
python封裝
雖然python3提供了asyncio這樣的異步IO庫,而且也有greenlet等其他協程庫,但目前的需求并不是實際的網絡IO并發操作,而是需要模擬狀態機的運行,因此使用協程可以很方便的模擬,并加入認為的控制,下面是封裝的一個python類。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
class Coroutine( object ): """ Base class of the general coroutine object """ STATE_RUNNING = 0 STATE_WAITING = 1 STATE_CLOSING = 2 def __init__( self ): self .state = Coroutine.STATE_WAITING self .started = False self .args = None self .routine = self ._co() def _co( self ): self .ret = None while True : self .args = yield self .ret if not self .started: self .started = True continue else : self .state = Coroutine.STATE_RUNNING self .ret = self .run( self .args) if self .state = = Coroutine.STATE_CLOSING: break self .state = Coroutine.STATE_WAITING def start( self ): """ Start the generator """ if self .routine is None : raise RuntimeError( 'NO task to start running!' ) self .started = True self .routine. next () def finish( self ): """ Finish the execution of this routine """ self .state = Coroutine.STATE_CLOSING self .routine.close() def run( self , args): """ The runing method to be executed every once time""" raise NotImplementedError def execute( self , arg_obj): """ Awake this routine to execute once time """ return self .routine.send(arg_obj) |
基于上述封裝,下面實現了一個協同的生產者消費者示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
class ProducerCoroutine(Coroutine): """ The Producer concrete coroutine """ def __init__( self , cnsmr): if not isinstance (cnsmr, Coroutine): raise RuntimeError( 'Consumer is not a Coroutine object' ) self .consumer = cnsmr self .consumer.start() super (ProducerCoroutine, self ).__init__() def run( self , args): print 'produce ' , args ret = self .consumer.execute(args) print 'consumer return:' , ret def __call__( self , args): """ Custom method for the specific logic """ self .start() while len (args) > 0 : p = args.pop() self .execute(p) self .finish() class ConsumerCoroutine(Coroutine): """ The Consumer concrete coroutine """ def __init__( self ): super (ConsumerCoroutine, self ).__init__() def run( self , args): print 'consumer get args: ' , args return 'hahaha' + repr (args) |
運行結果如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
produce 4 consumer get args: 4 consumer return : hahaha4 produce 3 consumer get args: 3 consumer return : hahaha3 produce 2 consumer get args: 2 consumer return : hahaha2 produce 1 consumer get args: 1 consumer return : hahaha1 produce 0 consumer get args: 0 consumer return : hahaha0 |
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:https://blog.csdn.net/u010487568/article/details/62042709