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

Jan Kaliszewski zuo at chopin.edu.pl
Thu Jun 16 01:15:36 CEST 2011


Steven D'Aprano dixit (2011-06-15, 21:35):

> This is another reason why function parameters should not be used for
> something that is not a function parameter!
> 
> +1 on the ability to inject locals into a function namespace.
> 
> -1 on having the syntax for that masquerade as function arguments.

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? 

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

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]

One question is whether it is technically possible to avoid introducing
a new keyword (e.g. staticlocal) explicitly marking injected locals.
Using such a keyword would be redundant from user point of view and
non-DRY:

    @functools.owns(cache=dict(), MAX_CACHE_LEN=100)  
    def calculate(a, b):
        staticlocal cache, MAX_CACHE_LEN  # <- redundant and non-DRY :-(
        result = cache[(a, b)]
        if result is not None:
            return result
        ...


2. Decorator function with argument-like injecting.

    @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 *can* be rebound to another object
        # than the injected object -- in the same way arguments can

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]

To implement such variant -- a new function constructor argument(s)
and/or function/function code attribute(s) (read-only or writable?)
most probably would have to be introduced...


3. Decorator-like language syntax construct:

    @in(cache=dict(), MAX_CACHE_LEN=100)  # or 'owns' or 'inject' or...
    def calculate(a, b):
        result = cache[(a, b)]
        if result is not None:
            return result
        ...
        # 'cache' identifier *can* be rebound to another object
        # than the injected object -- in the same way arguments can

It would not be a real decorator function -- so it would be applicable
only using this syntax, and not dynamically, not after function creation.


Which do you prefer? (or any other?)

Regards.
*j




More information about the Python-ideas mailing list