22# -*- coding: utf-8 -*-
33
44"""http://www.testingperspective.com/wiki/doku.php/collaboration/chetan/designpatternsinpython/chain-of-responsibilitypattern"""
5+ """http://www.dabeaz.com/coroutines/"""
6+
7+ import time
8+ import os
9+ import sys
10+ from contextlib import contextmanager
511
612class Handler :
7- def __init__ (self ,successor ):
8- self ._successor = successor ;
9- def handle (self ,request ):
10- i = self ._handle (request )
11- if not i :
13+ def __init__ (self , successor = None ):
14+ self ._successor = successor
15+ def handle (self , request ):
16+ res = self ._handle (request )
17+ if not res :
1218 self ._successor .handle (request )
1319 def _handle (self , request ):
1420 raise NotImplementedError ('Must provide implementation in subclass.' )
@@ -43,16 +49,95 @@ def _handle(self, request):
4349
4450class Client :
4551 def __init__ (self ):
46- self .handler = ConcreteHandler1 (ConcreteHandler3 (ConcreteHandler2 (DefaultHandler (None ))))
52+ self .handler = ConcreteHandler1 (ConcreteHandler3 (ConcreteHandler2 (DefaultHandler ())))
4753 def delegate (self , requests ):
4854 for request in requests :
4955 self .handler .handle (request )
5056
5157
58+ def coroutine (func ):
59+ def start (* args , ** kwargs ):
60+ cr = func (* args , ** kwargs )
61+ cr .next ()
62+ return cr
63+ return start
64+
65+ @coroutine
66+ def coroutine1 (target ):
67+ while True :
68+ request = yield
69+ if 0 < request <= 10 :
70+ print ('request {} handled in coroutine 1' .format (request ))
71+ else :
72+ target .send (request )
73+
74+ @coroutine
75+ def coroutine2 (target ):
76+ while True :
77+ request = yield
78+ if 10 < request <= 20 :
79+ print ('request {} handled in coroutine 2' .format (request ))
80+ else :
81+ target .send (request )
82+
83+ @coroutine
84+ def coroutine3 (target ):
85+ while True :
86+ request = yield
87+ if 20 < request <= 30 :
88+ print ('request {} handled in coroutine 3' .format (request ))
89+ else :
90+ target .send (request )
91+
92+ @coroutine
93+ def default_coroutine ():
94+ while True :
95+ request = yield
96+ print ('end of chain, no coroutine for {}' .format (request ))
97+
98+ class ClientCoroutine :
99+ def __init__ (self ):
100+ self .target = coroutine1 (coroutine3 (coroutine2 (default_coroutine ())))
101+
102+ def delegate (self , requests ):
103+ for request in requests :
104+ self .target .send (request )
105+
106+ def timeit (func ):
107+
108+ def count (* args , ** kwargs ):
109+ start = time .time ()
110+ res = func (* args , ** kwargs )
111+ count ._time = time .time () - start
112+ return res
113+ return count
114+
115+ @contextmanager
116+ def suppress_stdout ():
117+ try :
118+ stdout , sys .stdout = sys .stdout , open (os .devnull , 'w' )
119+ yield
120+ finally :
121+ sys .stdout = stdout
122+
123+
52124if __name__ == "__main__" :
53- client = Client ()
125+ client1 = Client ()
126+ client2 = ClientCoroutine ()
54127 requests = [2 , 5 , 14 , 22 , 18 , 3 , 35 , 27 , 20 ]
55- client .delegate (requests )
128+
129+ client1 .delegate (requests )
130+ print ('-' * 30 )
131+ client2 .delegate (requests )
132+
133+ requests *= 10000
134+ client1_delegate = timeit (client1 .delegate )
135+ client2_delegate = timeit (client2 .delegate )
136+ with suppress_stdout ():
137+ client1_delegate (requests )
138+ client2_delegate (requests )
139+ # lets check what is faster
140+ print (client1_delegate ._time , client2_delegate ._time )
56141
57142### OUTPUT ###
58143# request 2 handled in handler 1
@@ -64,3 +149,14 @@ def delegate(self, requests):
64149# end of chain, no handler for 35
65150# request 27 handled in handler 3
66151# request 20 handled in handler 2
152+ # ------------------------------
153+ # request 2 handled in coroutine 1
154+ # request 5 handled in coroutine 1
155+ # request 14 handled in coroutine 2
156+ # request 22 handled in coroutine 3
157+ # request 18 handled in coroutine 2
158+ # request 3 handled in coroutine 1
159+ # end of chain, no coroutine for 35
160+ # request 27 handled in coroutine 3
161+ # request 20 handled in coroutine 2
162+ # (0.2369999885559082, 0.16199994087219238)
0 commit comments