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

Reply via email to