[Python-ideas] 'Injecting' objects as function-local constants
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
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
glbs = func.__globals__
def inner(*args, **kwargs):
with _modifyGlobals(glbs, localArgs):
ret = func(*args, **kwargs)
def _modifyGlobals(glbls, additions):
frmglbls = glbls.copy()
And demonstrating it in use:
>>> def func(obj):
... 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>
>>> newfunc() # New function uses injected len.
<function <lambda> at 0xb7c2f86c>
And as a decorator:
... def spam():
>>> a = 42
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.
More information about the Python-ideas