using "private" parameters as static storage?

Joe Strout joe at strout.net
Thu Nov 13 22:51:47 EST 2008


Hi Luis,

> A lot of languages have ditched the "concept" of a static variable  
> on a method (how do
> you parse that sentence, btw?) in favour of using encapsulation.

A static variable IS encapsulation.  Encapsulation happens at many  
levels: module, class, instance, and (in languages that support it)  
method.  A static local variable is simply the finest level of  
encapsulation.  (Well, actually you could go one finer in some  
languages and have block-level static scope.)

> * With closures:
>
> ===
> def myfunc():
>    pseudo_static_list = []
>    def real_function(args):
>         pseudo_static_list.append(args)
>         print pseudo_static_list
>    return real_function
> myfunc = myfunc()

That's interesting -- I'll need to study it further before I really  
understand it, so thanks very much.  (That's why I ask these  
questions; I'm hoping there is some Python feature I haven't yet fully  
grokked which applies to the problem at hand.)

> Caveat: you cannot assign, as in python 2.5 at least, to the closure  
> variable -
> doing so would create a local variable instead.

Makes sense.

> * With default argument:
> ===
> def myfunc(normal_args, _hidden_arg=[]):
>    _hidden_arg.append(normal_args)
>    print _hidden arg
> ===
> (You can't shouldn't to _hidden_arg either, and you risk someone  
> invoking the
> function with that argument)

Right, that was my first idea.  Though it's in the "gentleman's  
agreement" spirit of Python.

> * With function's instance members:
> ===
> def myfunc(args):
>    myfunc.counter=1 # well, you should use some logic to see if it's  
> not
>                     # initialized
>    myfunc.counter+=1
>    print myfunc.counter

That was my second idea.

> Instance attributes beats them all, though.

No, just adding an instance attribute to the class the method is  
already on does not give you the same semantics at all, unless the  
class happens to be a singleton.  Otherwise, each instance would get  
its own cache (or count or whatever -- there are several different use  
cases I've seen for this), rather than a shared one.  Sometimes that's  
acceptable, but often it's not.

As noted before, the obvious solution in this case is to use a module-  
or class-level variable, prefixed with an underscore.  That's not  
horrible, but I wanted to explore possible alternatives.

>> I understand very well when data should be stored as instance data,  
>> and when it
>> should be instead tucked away as static data within a method.
>
> OT: Please enlighthen me. I didn't grew with C, and even when I saw C 
> ++,
> instance variables made a lot more sense to me that 'static'  
> variables.

Maybe a couple examples will help:

1. You have an instance method whose job it is to map something to  
something else (e.g. zip codes to city names), say by looking it up in  
a big file or database.  Per the "lazy initialization" strategy, you  
don't want to look stuff up before it's needed, but you find that  
looking it up every time causes big performance problems (because  
whatever zip codes are in use at the time get used a lot, and the file  
or DB access is slow).  Moreover, the object is lightweight and you're  
going to have a lot of them coming and going, so just caching the  
result on the instance won't help much.  You instead need a cache that  
sticks around for the life of the app, like a class or module  
attribute.  But because the existence of that cache is an  
implementation detail internal to this method, and shouldn't be  
anybody else's business, you want to tuck it away inside that method.

2. You have an object which, among other things, can create other  
objects.  Part of its job is to assign the newly created objects ID  
numbers which must be unique across the entire application (maybe  
they're wx identifiers or used for serialization or whatever).  So it  
needs to keep track of what the next available ID is.  But again, if  
you consider that to be implementation detail internal to the factory  
method, then it should be encapsulated inside that method.  And  
storing it on the factory-object instance won't do, because you need  
the IDs to be unique even across instances.

>> If you don't understand that, or are happy without having the  
>> choice, and have no answer to the question I
>> was asking, then that's fine.
>
> I believe he had an answer... You didn't like it, though.

If he had an answer to the question I was asking, he didn't share it.   
I asked "what's the best way to do this?"  Several responses ignored  
that question, and instead said, "Don't do that."

If you ask me how to cook an omelet, I might say "don't eat omelets;  
pancakes are much tastier, you should eat them instead."  But that  
doesn't tell you how to cook an omelet, does it?

> I hope mine was more palatable to you.

Yours was tasty indeed, thanks very much!

Cheers,
- Joe




More information about the Python-list mailing list