[Python-ideas] 'Injecting' objects as function-local constants
Steven D'Aprano
steve at pearwood.info
Fri Jun 17 07:37:46 CEST 2011
Nick Coghlan wrote:
> On Fri, Jun 17, 2011 at 3:15 AM, Jan Kaliszewski <zuo at chopin.edu.pl> wrote:
>> or even (to stress that it is a language syntax construct:
>>
>> @inject mem=collections.Counter(), MAX_MEM=1000
>> def do_and_remember(val, verbose=False):
>
> While that would require the from__future__ dance to make "inject" a
> new keyword, I like it much better than the
> looks-like-a-decorator-but-isn't syntax.
What benefit is there in making inject a keyword? Even super isn't a
keyword.
As far as I'm concerned, inject need only be a function in the functools
module, not even a built-in, let alone a keyword.
Here's a quick and dirty version that comes close to the spirit of
inject, as I see it. Thanks to Alex Light's earlier version.
# Credit to Alex Light.
from contextlib import contextmanager
from functools import wraps
def inject(**localArgs):
def decorator(func):
glbs = func.__globals__
@wraps(func)
def inner(*args, **kwargs):
with _modifyGlobals(glbs, localArgs):
ret = func(*args, **kwargs)
return ret
return inner
return decorator
@contextmanager
def _modifyGlobals(glbls, additions):
frmglbls = glbls.copy()
try:
glbls.update(additions)
yield
finally:
glbls.clear()
glbls.update(frmglbls)
And demonstrating it in use:
>>> def func(obj):
... print(len)
... return len(obj)+1
...
>>> import builtins
>>> newfunc = inject(len=lambda o: print(o) or builtins.len(o))(func)
>>>
>>> func([]) # Original function unchanged, still uses uninjected len.
<built-in function len>
1
>>> newfunc([]) # New function uses injected len.
<function <lambda> at 0xb7c2f86c>
[]
1
And as a decorator:
>>> @inject(a=1)
... def spam():
... print(a)
...
>>> a = 42
>>> spam()
1
Unfortunately, this proof-of-concept inject function doesn't actually
inject into locals, hence the "import builtins" work-around. But it
demonstrates the intent, and the API.
--
Steven
More information about the Python-ideas
mailing list