zephyr
zephyr

Reputation: 2332

Create a method attribute in a class

I can create a function of the following format.

def bar():
    if not hasattr(bar, 'c'):
        bar.c = 0
    bar.c += 1
    return bar.c

When run it produces the following output, as intended:

>>> bar()
1
>>> bar()
2
>>> bar()
3

But if I suddenly move this function to a class, Python gives me an error.

class Foo(object):

    def bar(self):
        if not hasattr(self.bar, 'c'):
            self.bar.c = 0
        self.bar.c += 1
        return self.bar.c

Now I get

>>> foo = Foo()
>>> foo.bar()
...
AttributeError: 'method' object has no attribute 'c'

It's telling me it has no attribute, but I'm trying to create the attribute. What's going on here?

Upvotes: 5

Views: 4038

Answers (1)

Sci Prog
Sci Prog

Reputation: 2691

Taken from the python documentation (https://docs.python.org/2/library/stdtypes.html?highlight=instancemethod) "However, since method attributes are actually stored on the underlying function object (meth.im_func), setting method attributes on either bound or unbound methods is disallowed."

In other words, we could have tried Foo.bar.im_func.c = 0, but unfortunately, it is read-only, so it doesn't work.

Therefore, for what you try to accomplish, I would suggest

class Foo(object):
  c = 0
  def bar(self):
    Foo.c += 1
    return Foo.c

f = Foo()
print f.bar()
print f.bar()
print f.bar()

Works on python2 and python3.

The only "drawback" is that c would be available to any other method of class Foo.

Upvotes: 5

Related Questions