[Python-ideas] 'Injecting' objects as function-local constants

Steven D'Aprano steve at pearwood.info
Thu Jun 16 02:46:51 CEST 2011

Jan Kaliszewski wrote:

> OK, so the decorator or decorator-like syntax (using 'inject', 'within',
> 'owns' or other decorator name...) seems to be the most promising
> alternative. If so, next question is: which variant? 

"owns"? I don't see how that testing for ownership describes what the 
function does.

Likewise for "within", which sounds like it should be a synonym for the 
"in" operator: "if value within range" sort of thing.

> 1. Decorator function with closure-like injecting
>    (possibly could be implemented using closures):
>     @functools.owns(cache=dict(), MAX_CACHE_LEN=100)  
>     def calculate(a, b):
>         result = cache[(a, b)]
>         if result is not None:
>             return result
>         ...
>         # 'cache' identifier cannot be rebound to another object
>         # because it was already used above in the function body
>         # to refer to the injected object

Making locals unrebindable is a change of semantics that is far beyond 
anything I've been discussed here. This will be a big enough change 
without overloading it with changes that will be even more controversial!

(I actually do like the idea of having unrebindable names, but that 
should be kept as a separate issue and not grafted on to this proposal.)

> functools.owns() would be a real decorator function -- to apply either with 
> @-syntax or dynamically, e.g.:
>     decorated = [functools.owns(func) for func in functions]

There shouldn't even be a question about that. Decorator syntax is sugar 
for func = decorator(func). Introducing magic syntax that is recognised 
by the compiler but otherwise is not usable as a function is completely 

If func is a pre-existing function:

def func(a, b, c):


new_func = functools.inject(x=1, y=2)(func)

should be the same as:

def new_func(a, b, c):
     # inject locals into the body of the function
     x = 1
     y = 2
     # followed by the body of the original

except that new_func.__name__ may still reflect the old name "func".

* If the original function previously referenced global or nonlocal x 
and y, the new function must now treat them as local;

* Bindings to x and y should occur once, at function definition time, 
similar to the way default arguments occur once;

* The original function (before the decorator applies) must be untouched 
rather than modified in place.

This implies to me that inject must copy the original function and make 
modifications to the code object. This sounds to me that a 
proof-of-concept implementation would be doable using a byte-code hack.


More information about the Python-ideas mailing list