Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: Python: Python

How to keep a function as a generator function when the yield operator is moved into its sub-functions??

 

 

Python python RSS feed   Index | Next | Previous | View Threaded


weafon at lbl

Jul 14, 2009, 11:03 AM

Post #1 of 4 (305 views)
Permalink
How to keep a function as a generator function when the yield operator is moved into its sub-functions??

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





--
http://mail.python.org/mailman/listinfo/python-list


milesck at umich

Jul 14, 2009, 11:24 AM

Post #2 of 4 (280 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]

On Jul 14, 2009, at 2:03 PM, weafon wrote:

> 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?

def func1():
...
while cond:
...
for x in commoncode():
yield x
...

See also:
- PEP 380: http://www.python.org/dev/peps/pep-0380/
- Stackless: http://www.stackless.com/

-Miles

--
http://mail.python.org/mailman/listinfo/python-list


davea at ieee

Jul 14, 2009, 8:32 PM

Post #3 of 4 (268 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]

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


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

Python python RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact Gossamer Threads
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.