using "private" parameters as static storage?

Joe Strout joe at strout.net
Fri Nov 14 13:05:38 EST 2008


On Nov 13, 2008, at 3:23 PM, Arnaud Delobelle wrote:

> Aaron Brady <castironpi at gmail.com> writes:
>
>> One way around it, which I like the idea of but I'll be honest, I've
>> never used, is getting a function a 'self' parameter.  You could make
>> it a dictionary or a blank container object, or just the function
>> itself.
>> ...
> Rummaging through my ~/python/junk/ I found the almost exact same:
>
> class NS(object):
>    def __init__(self, dict):
>        self.__dict__.update(dict)
>
> def static(**vars):
>    ns = NS(vars)
>    def deco(f):
>        return lambda *args, **kwargs: f(ns, *args, **kwargs)
>    return deco
>
> @static(ncalls=0, history=[])
> def foo(ns, x):
>   ns.ncalls += 1
>   ns.history.append(x)
>   print "Number of calls: %s\nHistory:%s" % (ns.ncalls, ns.history)

Thanks, Arnaud (and Aaron), that's really clever.  I was thinking this  
morning that something like this might be possible: a decorator that  
adds the static storage with some standard name.  I really like how  
you've set this so that the static data is initialized right in the  
decorator; that makes the intent very clear and hard to screw up.

My only regret with this one is the need to add "ns" to the parameter  
list.  That makes it lok like part of the signature, when really (in  
intent) it is not.  If we have to add something to the parameter list,  
we may as well do this:

def foo(x, _ns=NS(ncalls=0, history=[])):
    ...

and skip the decorator.  Then at least it's clear that this parameter  
isn't really intended for callers.  On the other hand, I guess the  
decorator actually changes the signature as seen by the calling code,  
which is a good thing.  Rearranging the parameter order in the  
decorator a bit, we could make this so that the intent is clear to the  
reader, as well as enforced by the interpreter.

Neat stuff, thank you!

Best,
- Joe







More information about the Python-list mailing list