2
2
# -*- coding: utf-8 -*-
3
3
4
4
"""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
5
11
6
12
class 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 :
12
18
self ._successor .handle (request )
13
19
def _handle (self , request ):
14
20
raise NotImplementedError ('Must provide implementation in subclass.' )
@@ -43,16 +49,95 @@ def _handle(self, request):
43
49
44
50
class Client :
45
51
def __init__ (self ):
46
- self .handler = ConcreteHandler1 (ConcreteHandler3 (ConcreteHandler2 (DefaultHandler (None ))))
52
+ self .handler = ConcreteHandler1 (ConcreteHandler3 (ConcreteHandler2 (DefaultHandler ())))
47
53
def delegate (self , requests ):
48
54
for request in requests :
49
55
self .handler .handle (request )
50
56
51
57
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
+
52
124
if __name__ == "__main__" :
53
- client = Client ()
125
+ client1 = Client ()
126
+ client2 = ClientCoroutine ()
54
127
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 )
56
141
57
142
### OUTPUT ###
58
143
# request 2 handled in handler 1
@@ -64,3 +149,14 @@ def delegate(self, requests):
64
149
# end of chain, no handler for 35
65
150
# request 27 handled in handler 3
66
151
# 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