On Nov 13, 4:13 pm, Paul McGuire <[EMAIL PROTECTED]> wrote: > On Nov 13, 3:08 pm, Aaron Brady <[EMAIL PROTECTED]> wrote: > > > > > On Nov 13, 11:16 am, Joe Strout <[EMAIL PROTECTED]> 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 ' > > > > This appears to work fine, but it feels a little unclean, having stuff > > > in the method signature that is only meant for internal use. Naming > > > the parameter with an underscore "_count" 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? > > > > 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. But then, if I renamed a function, > > > I'd have to change all the callers anyway. So maybe this is better. > > > What do y'all think? > > > Worse yet, if you define a duplicate object at the same scope with the > > same name later, it breaks all your references within the function to > > itself. > > > One way around it, which I like the idea of but I'll be honest, I've > > never used, is getting a function a 'self' parameter. You could make > > it a dictionary or a blank container object, or just the function > > itself. > > > @self_param > > def spam( self ): > > self._count[0] += 1 #<--- how to initialize? > > return "spam " * self._count[0] > > > Only problem is, how do you initialize _count? > > > Perhaps 'self_param' can take some initializers, and just initialize > > them off of **kwargs in the construction. > > > @self_param( _count= [] ) > > def spam( self ): > > self._count[0] += 1 > > return "spam " * self._count[0] > > > Looks really pretty (imo), but untested.- Hide quoted text - > > > - Show quoted text - > > Initialization does not have to be in the body of the method. > > >>> def spam(): > > ... spam._count[0] += 1 #<--- how to initialize? see below > ... return "spam " * spam._count[0] > ...>>> spam._count = [2] # just initialize it, and not necessarily to 0 > >>> spam() > 'spam spam spam ' > >>> spam() > > 'spam spam spam spam ' > >>> spam() > > 'spam spam spam spam spam '
That is actually susceptible to a subtle kind of bug: >>> def spam( ): ... spam._count[0] += 1 ... return "spam " * spam._count[0] ... >>> spam._count=[2] >>> spam() 'spam spam spam ' >>> f= spam >>> f() 'spam spam spam spam ' >>> spam= 'spam and eggs' >>> f() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in spam AttributeError: 'str' object has no attribute '_count' It would be worse if you assigned 'spam' to another function! Of course one option is 'just don't do that', which is alright. Adding the self parameter is just a second option, if you need the function to change names. Though the decorator is a nice place for the initialization. -- http://mail.python.org/mailman/listinfo/python-list