An attribute is a variable that is viewed on another object using the dotted syntax: obj.attribute . The Python path is designed, attribute searching can do many things, and this variety can sometimes lead to errors if you really don’t understand what is happening (this is what documentation related information warns about).
The most basic problem is that the attribute search can either find the value stored in the dictionary of the instance of the object, or it can find something from the class of the object (or the base class if inheritance occurs). Methods are functions stored in a class, but you usually use them by looking at them on an instance (which “binds” the method, inserting the object as the first argument when the method is called).
The exact sequence of what is checked when a bit complicated (I described the complete process in an answer to another question ), but at the most basic level, instance attributes usually take precedence over a class attribute.
If an instance attribute and a class attribute with the same name exist, usually only the instance attribute is available. This can be very confusing if it is unintentional.
Consider the following code:
class Foo(object): def __init__(self, lst): self.lst = lst def sum(self): self.sum = sum(self.lst) return self.sum f = Foo([1,2,3]) print(f.sum()) print(f.sum())
At the bottom of this code, we make two identical calls. The first works just fine, but the second throws an exception.
This is due to the fact that the first f.sum we search for f.sum we find a method in the Foo class. We can name the method without problems. The problem is that the sum method assigns the result of its calculation (the sum of the elements in self.lst ) to the instance attribute, also called sum . This hides the sum method from the view.
When the second call to f.sum() looks up f.sum , it finds an instance attribute containing the integer 6 , not the expected method. An integer is not callable, so we get an exception.
The solution, of course, should not use the same name for the method and attribute. The above code is a pretty simple example. Errors caused by such things in more complex code can be much harder to figure out.
If you write code that adds attributes to objects that you know little about, you should be careful to avoid common names. If you are writing a mixin class, consider using two leading underscores in attribute names to trigger the Python name manipulation, which is designed specifically for this kind of situation.