using "private" parameters as static storage?
Bruno Desthuilliers
bruno.42.desthuilliers at websiteburo.invalid
Fri Nov 14 05:31:43 EST 2008
Joe Strout a écrit :
> One thing I miss as I move from REALbasic to Python is the ability to
> have static storage within a method
s/method/function/
> -- 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]
>
> >>> spam()
> 'spam '
> >>> spam()
> 'spam spam '
>
> This appears to work fine, but it feels a little unclean, having stuff
> in the method signature that is only meant for internal use.
It's indeed a hack. But it's a very common one, and
> Naming the
> parameter with an underscore "_count"
is also a pretty idiomatic way to warn that it's implementation-only.
> makes me feel a little better
> about it.
> But then, adding something to the module namespace just for
> use by one function seems unclean too.
> What are your opinions on this idiom? Is there another solution people
> generally prefer?
If it's really in a *method*, you can always use a class (or instance,
depending on concrete use case) attribute. Else, if you really insist on
cleanliness, you can define your own callable:
class Spammer(object):
def __init__(self):
self._count = 0
def __call__(self):
self._count += 1
return "spam " * self._count
spam = Spammer()
But this might be a little overkill for most concrete use case.
NB : you'll also have to implement __get__ if you want Spammer instances
to be used as methods.
> 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.
There's another drawback:
old_spam2 = spam2
def spam2():
print "yadda yadda", old_spam2()
Remember that Python functions are ordinary objects...
More information about the Python-list
mailing list