[Python-Dev] Re: anonymous blocks
Nick Coghlan
ncoghlan at gmail.com
Tue Apr 26 17:14:51 CEST 2005
Michael Hudson wrote:
> This is a non-starter, I hope. I really meant what I said in PEP 310
> about loops being loops.
The more I play with this, the more I want the 'with' construct to NOT be a loop
construct.
The main reason is that it would be really nice to be able to write and use a
multipart code template as:
def template():
# pre_part_1
yield None
# post_part_1
yield None
# pre_part_2
yield None
# post_part_2
yield None
# pre_part_3
yield None
# post_part_3
def user():
block = template()
with block:
# do_part_1
with block:
# do_part_2
with block:
# do_part_3
If 'with' is a looping construct, the above won't work, since the first usage
will drain the template.
Accordingly, I would like to suggest that 'with' revert to something resembling
the PEP 310 definition:
resource = EXPR
if hasattr(resource, "__enter__"):
VAR = resource.__enter__()
else:
VAR = None
try:
try:
BODY
except:
raise # Force realisation of sys.exc_info() for use in __exit__()
finally:
if hasattr(resource, "__exit__"):
VAR = resource.__exit__()
else:
VAR = None
Generator objects could implement this protocol, with the following behaviour:
def __enter__():
try:
return self.next()
except StopIteration:
raise RuntimeError("Generator exhausted, unable to enter with block")
def __exit__():
try:
return self.next()
except StopIteration:
return None
def __except__(*exc_info):
pass
def __no_except__():
pass
Note that the code template can deal with exceptions quite happily by utilising
sys.exc_info(), and that the result of the call to __enter__ is available
*inside* the with block, while the result of the call to __exit__ is available
*after* the block (useful for multi-part blocks).
If I want to drain the template, then I can use a 'for' loop (albeit without the
cleanup guarantees).
Taking this route would mean that:
* PEP 310 and the question of passing values or exceptions into iterators
would again become orthogonal
* Resources written using generator syntax aren't cluttered with the
repetitive try/finally code PEP 310 is trying to eliminate
* 'for' remains TOOW to write an iterative loop
* it is possible to execute _different_ suites between each yield in the
template block, rather than being constrained to a single suite as in the
looping case.
* no implications for the semantics of 'return', 'break', 'continue'
* 'yield' would not be usable inside a with block, unless the AbortIteration
concept was adopting for forcible generator termination.
Cheers,
Nick.
--
Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia
---------------------------------------------------------------
http://boredomandlaziness.skystorm.net
More information about the Python-Dev
mailing list