[Python-Dev] Merging PEP 310 and PEP 340-redux?
Phillip J. Eby
pje at telecommunity.com
Tue May 10 18:58:36 CEST 2005
At 08:51 AM 5/10/2005 -0700, Guido van Rossum wrote:
>[Phillip J. Eby]
> > Yeah, I'd ideally like to see __try__, __except__, __else__, and
> > __finally__ methods, matching the respective semantics of those clauses in
> > a try/except/finally block.
>
>What's your use case for adding this complexity?
It makes it much easier to mentally translate a given
try/except/else/finally usage to a "resource" or "block controller" or
whatever it is we're calling these things now. You should almost be able
to just stick 'def __' and '__(self):' and then munge the whole thing into
a class.
Of course, it's not *really* that simple, because __try__ doesn't exactly
correspond to 'try:', and it has to return something, but it sure is
simpler than the mental gymnastics I'd go through to convert
except/else/finally into "if" statements inside an __exit__.
Granted, if we end up with __enter__ and __exit__, I'll just write a
resource mixin class whose __exit__ calls a stubbed-out __except__,
__else__, and __finally__. Then I won't have to figure out how to write
__exit__ methods all the time. Which is great for me, but I was thinking
that this interface would reduce complexity for people trying to learn how
to write these things.
I wasn't advocating this before because PEP 340's use of generators allowed
you to directly use try/except/else/finally. But, the new approach seems
targeted at a wider set of use cases that don't include generators. IOW,
it's likely you'll be adding resource-finalization methods to actual
resource classes, and grafting generators into them to implement
__enter__/__exit__ seems more complex at first glance than just letting
people add the methods directly; e.g.:
def __enter__(self):
self.handler = self._resource_control()
return self.handler.__enter__()
def __exit__(self):
self.handler.__exit__()
@with_template
def _resource_control(self):
f = self.open("blah")
try:
yield f
finally:
f.close()
versus this rather more "obvious way" to do it:
def __try__(self):
self.f = self.open("blah")
return self.f
def __finally__(self):
self.f.close()
But I suppose you could encapsulate either pattern as a mixin class, so I
suppose this could be treated as a matter for examples in documentation
rather than as an implementation aspect. It's just that if __exit__ has to
probe exception state or other wizardry, it's going to be harder for
non-wizards to use, and that's what I was reacting to here. Anyway, I see
now that documentation and simple mixins could address it, so if you think
it's best handled that way, so be it.
> I'm going for simple
>here unless there's a really strong use case. Anyway, a wrapped
>generator wrapper can't do with all those distinctions unless we
>augment the generator somehow ("continue EXPR" would suffice).
You'd use only __try__, __except__, and __else__ to wrap a generator. For
some other use cases you'd only use __try__ and __finally__, or __try__ and
__except__, or __try__ and __else__. I don't know of any use cases where
you'd want to use all four simultaneously on the same controller.
>(Your decorator is equivalent to mine, but I don't like creating a new
>class each time.)
Mine was just a sketch to show the idea anyway; I'd be surprised if it
doesn't have at least one bug.
More information about the Python-Dev
mailing list