using "private" parameters as static storage?
J. Cliff Dyer
jcd at sdf.lonestar.org
Thu Nov 13 13:32:22 EST 2008
On Thu, 2008-11-13 at 09:38 -0800, Matimus wrote:
> On Nov 13, 9:16 am, Joe Strout <j... at strout.net> 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]
> >
> > >>> spam()
> > 'spam '
> > >>> spam()
> > 'spam spam '
> >
>
> Don't Do this, it is confusing and there are definitely (many) better
> facilities in python for handling saved state.
>
>
> > 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 is definitely preferred over the first. However the preferred
> method is just to use a class. Preserving state is what classes are
> for.
>
Preserving state is what *objects* are for. Even the builtins have
state to be preserved (list.__len__, func.func_code, for example).
Classes are for creating custom objects.
> >>> class Spam(object):
> ... def __init__(self):
> ... self._count = 0
> ... def spam(self):
> ... self._count += 1
> ... return " ".join("spam" for _ in xrange(self._count))
> ...
Oh of course. This is a much cleaner way to return the response than
the one I used. (FYI, I used: `return ("spam " * self._count).rstrip()`
and I didn't like the rstrip even when I was doing it. Dunno why I
didn't think of it.)
> >>> class Spam(object):
> ... def __init__(self):
> ... self._count = 0
> ...
> ... def spam(self):
> ... self._count += 1
> ... return " ".join("spam" for _ in xrange(self._count))
> ...
> ... __call__ = spam
> ...
Interesting. I hadn't thought of making __call__ a synonym for an
existing method. I think I like that, but I'm not quite sure. There's
something that nags at me about having two ways to do the same thing,
but I like giving the method a more descriptive name than __call__.
Cheers,
Cliff
More information about the Python-list
mailing list