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...
--
http://mail.python.org/mailman/listinfo/python-list