On Nov 13, 2008, at 11:15 AM, J. Cliff Dyer wrote:
Here are a few essays into the matter
def foo():
... foo._count += 1
... return ("spam " * foo.count).rstrip()
Simple and straightforward, and _count is still encapsulated in the
function, but it's kind of ugly, because when the function has been
defined, it is not functional.
Right, though the hasattr() check I put in my version of this approach
takes care of that.
Attempt #2 -- put it in a decorator
def add_counter(f):
... f._count = 0
... return f
...
@add_counter
... def foo():
... foo._count += 1
... return ("spam " * foo._count).rstrip()
Now THAT is something that hadn't occurred to me! I haven't really
studied decorators yet (and I'm pretty sure Python didn't have them
when I was last into it a decade ago). This is an interesting solution.
Now it's complete as soon as the function is defined, but the
decorator
is tightly bound to the function, in its use of _count. I find that
kind of ugly.
True. And we have two functions where we really only wanted one --
that's probably worse than just having a function plus a module-level
variable. Unless, perhaps, we could make a generic "has_cache"
decorator that can be reused in any method that needs some static
storage.
Try three. Let's put it in a class:
class Foo(object):
... def __init__(self, counter_start=0):
... self._count = counter_start
... def __call__(self):
... self._count += 1
... return ("spam " * self._count).rstrip()
At first I thought this suggestion was just to add an instance
variable to whatever class my method was already in, which violates
encapsulation at the level I'm after. But now I see this is is
something more subtle: you've made a callable object. We'd presumably
combine this with a Singleton pattern to get the desired semantics.
This is clever, but an awful lot of code for such a simple need.
Essentially, this has the same behavior as the other two. But it
looks
cleaner, and you don't have to worry about coupling separate
functions,
or refering to a function by name within itself (because you have self
to work with).
True. Pity there isn't a way for a function to get a reference to
itself except by name. Still, when you rename a method, you're going
to have to update all the callers anyway -- updating a couple of extra
references within the method is not that much extra effort.
All of these approaches may turn out to be more trouble than they're
worth; a module variable isn't THAT ugly. But it's nice to have some
options.
At any rate, you (and rurpy) have taken the time to consider the
question I was actually asking, instead of arguing with me whether I
should be asking it. I really appreciate that. Your suggestions are
helpful and have taught me some new Python tricks. Thanks very much!
Best,
- Joe
--
http://mail.python.org/mailman/listinfo/python-list