python: What happens when class attribute, instance attribute, and method all have the same name?

naren picture naren · Oct 18, 2012 · Viewed 15.1k times · Source

How does python differentiate a class attribute, instance attribute, and method when the names are the same?

class Exam(object):

    test = "class var"

    def __init__(self, n):
        self.test = n

    def test(self):
        print "method : ",self.test

test_o = Exam("Fine")

print dir(test_o)

print Exam.test
print test_o.test
test_o.test()

Output :

['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__',    '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'test']
<unbound method load.test>
Fine
Traceback (most recent call last):
  File "example.py", line 32, in <module>
    test_o.test()
TypeError: 'str' object is not callable

How to call

  1. class attribute, Exam.test --> <unbound method load.test> output shows method
  2. instance attribute test_o.test --> "Fine"
  3. method test_o.test() --> TypeError: 'str' object is not callable

Answer

Bakuriu picture Bakuriu · Oct 18, 2012

Class attributes are accessible through the class:

YourClass.clsattribute

or through the instance (if the instance has not overwritten the class attribute):

instance.clsattribute

Methods, as stated by ecatmur in his answer, are descriptors and are set as class attributes.

If you access a method through the instance, then the instance is passed as the self parameter to the descriptor. If you want to call a method from the class, then you must explicitly pass an instance as the first argument. So these are equivalent:

instance.method()
MyClass.method(instance)

Using the same name for an instance attribute and a method will make the method hidden via the instance, but the method is still available via the class:

#python3
>>> class C:
...     def __init__(self):
...         self.a = 1
...     def a(self):
...         print('hello')
... 
>>> C.a
<function a at 0x7f2c46ce3c88>
>>> instance = C()
>>> instance.a
1
>>> C.a(instance)
hello

Conclusion: do not give the same name to instance attributes and methods. I avoid this by giving meaningful names. Methods are actions, so I usually use verbs or sentences for them. Attributes are data, so I use nouns/adjectives for them, and this avoids using the same names for both methods and attributes.

Note that you simply cannot have a class attribute with the same name as a method, because the method would completely override it (in the end, methods are just class attributes that are callable and that automatically receive an instance of the class as first attribute).