
weafon at lbl
Jul 15, 2009, 9:48 AM
Post #4 of 4
(266 views)
Permalink
|
|
Re: How to keep a function as a generator function when the yield operator is moved into its sub-functions??
[In reply to]
|
|
Hi DaveA, Thank for your responses even though my problem has been solved based on Miles' suggestion. I am writing programs by using the SimPy library, which is a discrete-event simulator library. Below is my actual code segment class RAID(Process): def ReqServ(self): while(now()<TM_End): yield get, self, self.queue, 1 orig_req=self.got[0] .... for devno in range (5): ... #---- Segment A begins new_loc= calcfunc(orig_req.loc) new_len= calcfunc(orig_req.len) new_req1= Req(self.cn_req, new_loc, new_len) yield put, self, self.disks[devno].queue,[new_req] self.cn_req+=1 new_req2= Req(self.cn_req, new_loc, new_len) yield put, self, self.disks[devno+5].queue,[new_req] self.cn_req+=1 #--- Segment A ends ... In the above example, ReqServ may pause at three lines of yield and return something. However, if I move the code segment A into a second function as following, then ReqServ will not pause and return things back to its caller after calling SegmentA(). class RAID(Process): def ReqServ(self): while(now()<TM_End): yield get, self, self.queue, 1 orig_req=self.got[0] .... for devno in range (5): ... self.SegmentA(orig_req.loc,orig_req.len) ... def SegmentA(self,loc,len): new_loc= calcfunc(loc) new_len= calcfunc(len) new_req1= Req(self.cn_req, new_loc, new_len) yield put, self, self.disks[devno].queue,[new_req] self.cn_req+=1 new_req2= Req(self.cn_req, new_loc, new_len) yield put, self, self.disks[devno+5].queue,[new_req] self.cn_req+=1 Based on Miles's suggestion, we can solve the problem by using 'return' in SegmentA() and keeping 'yield' in ReqServ(). For example, class RAID(Process): def ReqServ(self): while(now()<TM_End): yield get, self, self.queue, 1 orig_req=self.got[0] .... for devno in range (5): ... yield self.SegmentA(orig_req.loc,orig_req.len,0) yield self.SegmentA(orig_req.loc,orig_req.len,5) ... def SegmentA(self,loc,len,shiftno): new_loc= calcfunc(loc) new_len= calcfunc(len) new_req= Req(self.cn_req, new_loc, new_len) self.cn_req+=1 return put, self, self.disks[devno+shiftno].queue,[new_req] Regards, Weafon Dave Angel wrote: > weafon wrote: >> <div class="moz-text-flowed" style="font-family: -moz-fixed">Hi guys, >> >> I have a question about the usage of yield. As shown in the below >> example, in general, if there is a code segment commonly used by two >> or more functions, we may isolate the segment into a function and >> then call it from other functions if necessary. >> >> def func1(): >> .... >> while(cond): >> ..... >> commoncode() >> ... >> >> >> def func2(): >> .... >> while(cond): >> ..... >> commoncode() >> ... >> >> def commoncode() >> AAAA >> BBBB >> CCCC >> >> However, if there is a 'yield' operation in the common code segment, >> the isolation causes that func1 and func2 become a non-generator >> function!! Although I can prevent such an isolation by just >> duplicating the segment in func1 and func2 to keep both of them being >> generator functions, the code may become ugly and hard to maintain >> particularly when coomoncode() is long. >> >> The problem may be resolved if I can define the commoncode() as an >> inline function or marco. Unfortunately, inline and marco do not >> seems to be implemented in python. Thus, how can I isolate a common >> segment into a function when there are yield operations in the common >> segment? >> >> Thanks, >> Weafon >> > You are implying there's something special or unique about yield in > this. Return has the same problem, and many other flow control > constructs. Also, variable definitions and scoping. > > So you can't just copy any old bunch of adjacent lines out of two > functions, put it into a third, and call it factoring. Give us a > specific example you're puzzled about, and we can try to solve it. > > DaveA > -- http://mail.python.org/mailman/listinfo/python-list
|