[Python-Dev] Bring new features to older python versions
PJ Eby
pje at telecommunity.com
Tue Oct 11 18:43:56 CEST 2011
On Tue, Oct 11, 2011 at 12:14 PM, Toshio Kuratomi <a.badger at gmail.com>wrote:
> This may not be the preferred manner to write decorators but it's fairly
> straightforward and easy to remember compared to, say, porting away from
> the
> with statement.
>
You can emulate 'with' using decorators, actually, if you don't mind a
nested function. Some code from my Contextual library (minus the tests):
*def* *call_with*(ctxmgr):
*"""Emulate the PEP 343 "with" statement for Python versions <2.5
The following examples do the same thing at runtime::
Python 2.5+ Python 2.4
------------ -------------
with x as y: @call_with(x)
print y def do_it(y):
print y
``call_with(foo)`` returns a decorator that immediately invokes the
function it decorates, passing in the same value that would be bound by
the ``as`` clause of the ``with`` statement. Thus, by decorating a
nested function, you can get most of the benefits of "with", at a cost of
being slightly slower and perhaps a bit more obscure than the 2.5 syntax.
Note: because of the way decorators work, the return value (if any) of the
``do_it()`` function above will be bound to the name ``do_it``. So, this
example prints "42"::
@call_with(x)
def do_it(y):
return 42
print do_it
This is rather ugly, so you may prefer to do it this way instead, which
more explicitly calls the function and gets back a value::
def do_it(y):
return 42
print with_(x, do_it)
"""*
*return* with_.__get__(ctxmgr, type(ctxmgr))
*def* *with_*(ctx, func):
*"""Perform PEP 343 "with" logic for Python versions <2.5
The following examples do the same thing at runtime::
Python 2.5+ Python 2.3/2.4
------------ --------------
with x as y: z = with_(x,f)
z = f(y)
This function is used to implement the ``call_with()`` decorator, but
can also be used directly. It's faster and more compact in the case where
the function ``f`` already exists.
"""*
inp = ctx.__enter__()
*try*:
retval = func(inp)
*except*:
*if* *not* ctx.__exit__(*sys.exc_info()):
*raise*
*else*:
ctx.__exit__(None, None, None)
*return* retval
This version doesn't handle the multi-context syntax of newer pythons, but
could probably be extended readily enough.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20111011/92c637f3/attachment.html>
More information about the Python-Dev
mailing list