Adding attributes to instance methods in Python
Question: I would like to add an attribute to an instance method in one of my classes. I
tried the answer given in [this
question](http://stackoverflow.com/questions/279561/what-is-the-python-
equivalent-of-static-variables-inside-a-function), but this answer only works
for functions -- as far as I can tell.

As an example, I would like to be able to do something like:

    
    
    class foo(object):
        ...
        def bar(self):
            self.bar.counter += 1
            return self.bar.counter
        bar.counter = 1
        ...
    

but, when I call foo().bar() I get:

    
    
    AttributeError: 'instancemethod' object has no attribute 'counter'
    

My goal in doing this is to try to impress that the 'counter' variable is
local to the bar() method, and also to avoid cluttering my class namespace
with yet another attribute. Is there a way to do this? Is there a more
pythonic way of doing this?


Answer: In Python 3 your code would work, but in Python 2 there is some wrapping that
takes place when methods are looked up.

# Class vs Instance

  * class level: storing `counter` with the function (either directly, or by using a mutable default) effectively makes it a class level attribute as there is only ever one of the function, no matter how many instances you have (they all share the same function object).

  * instance level: to make `counter` an instance level attribute you have to create the function in `__init__`, then wrap it with `functools.partial` (so it behaves like a normal method), and then store it on the instance -- now you have one function object for every instance.

# Class Level

The accepted practice for a static-like variable is to use a mutable default
argument:

    
    
    class foo(object):
        ...
        def bar(self, _counter=[0]):
            _counter[0] += 1
            return _counter[0]
    

If you want it to be prettier you can define your own mutable container:

    
    
    class MutableDefault(object):
        def __init__(self, start=0):
            self.value = start
        def __iadd__(self, other):
            self.value += other
            return self
        def value(self):
            return self.value
    

and change your code like so:

    
    
    class foo(object):
        def bar(self, _counter=MutableDefault()):
            _counter += 1
            return _counter.value
    

# Instance level

    
    
    from functools import partial
    
    class foo(object):
        def __init__(self):
            def bar(self, _counter=MutableDefault(1)):   # create new 'bar' each time
                value = _counter.value
                _counter += 1
                return value
            self.bar = partial(bar, self)
    

# Summary

As you can see, readability took a serious hit when moving to instance level
for `counter`. I strongly suggest you reevaluate the importance of emphasizing
that `counter` is part of `bar`, and if it is truly important maybe making
`bar` its own class whose instances become part of the instances of `foo`. If
it's not really important, do it the normal way:

    
    
    class foo(object):
        def __init__(self):
            self.bar_counter = 0
        def bar(self):
            self.bar_counter += 1
            return self.bar_counter
    

