[Python-ideas] Yield-From: Finalization guarantees

Jacob Holm jh at improva.dk
Thu Mar 26 15:16:42 CET 2009


Greg Ewing wrote:
> Jacob Holm wrote:
>
>>  Can you explain in a little more detail how the inlining argument 
>> makes you want to not catch a StopIteration escaping from throw?
> [snip explanation]
Thank you very much for the clear explanation.  It seems each of us were 
missing something.  AFAICT your latest expansion (reproduced below) 
fixes this.

I have a few (final, I hope) nits to pick about the finally clause. 

To start with there is no need for a separate "try".  Just adding the 
finally clause to the next try..except..else has the exact same semantics. 

Then there is the contents of the finally clause.  It is either too much 
or too little, depending on what it is you are trying to specify.  If 
the intent is to show that the last reference from the expansion to _i 
disappears here, it fails because _m is likely to hold a reference as 
well.  In any case I don't see a reason to single out _i for deletion.   
I suggest just dropping the finally clause altogether to make it clear 
that we are not promising any finalization beyond what is explicit in 
the rest of the code.

- Jacob

------------------------------------------------------------------------

     _i = iter(EXPR)
     try:
         try:
             _y = _i.next()
         except StopIteration, _e:
             _r = _e.value
         else:
             while 1:
                 try:
                     _s = yield _y
                 except:
                     _m = getattr(_i, 'throw', None)
                     if _m is not None:
                         _x = sys.exc_info()
                         try:
                             _y = _m(*_x)
                         except StopIteration, _e:
                             if _e is _x[1]:
                                 raise
                             else:
                                 _r = _e.value
                                 break
                     else:
                         _m = getattr(_i, 'close', None)
                         if _m is not None:
                             _m()
                         raise
                 else:
                     try:
                         if _s is None:
                             _y = _i.next()
                         else:
                             _y = _i.send(_s)
                     except StopIteration, _e:
                         _r = _e.value
                         break
     finally:
         del _i
     RESULT = _r




More information about the Python-ideas mailing list