using "private" parameters as static storage?

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Fri Nov 14 04:26:04 CET 2008


On Thu, 13 Nov 2008 10:16:59 -0700, Joe Strout wrote:

> One thing I miss as I move from REALbasic to Python is the ability to
> have static storage within a method -- i.e. storage that is persistent
> between calls, but not visible outside the method.  I frequently use
> this for such things as caching, or for keeping track of how many
> objects a factory function has created, and so on.
> 
> Today it occurred to me to use a mutable object as the default value of
> a parameter.  A simple example:
> 
> def spam(_count=[0]):
>       _count[0] += 1
>       return "spam " * _count[0]

This is a common trick, often used for things like caching. One major 
advantage is that you are exposing the cache as an *optional* part of the 
interface, which makes testing easier. For example, instead of a test 
that looks something like this:


cache = get_access_to_secret_cache()  # somehow
modify(cache)
result = function(arg)
restore(cache)
assert something_about(result)

you can simple do this:

result = function(arg, _cache=mycache)
assert something_about(result)


Periodically people complain that Python's mutable default argument 
behaviour is a problem, and ask for it to be removed. I agree that it is 
a Gotcha that trips up newbies, but it is far to useful to give up, and 
simple caching is one such reason.


> Ooh, for a change I had another thought BEFORE hitting Send rather than
> after.  Here's another trick:
> 
> def spam2():
>       if not hasattr(spam2,'count'):spam2.count=0 spam2.count += 1
>       return "spam2 " * spam2.count
> 
> This doesn't expose any uncleanliness outside the function at all. The
> drawback is that the name of the function has to appear several times
> within itself, so if I rename the function, I have to remember to change
> those references too.  But then, if I renamed a function, I'd have to
> change all the callers anyway.  So maybe this is better. What do y'all
> think?

I've used this myself, but to me it feels more icky than the semi-private 
argument trick above.




-- 
Steven



More information about the Python-list mailing list