== Python's attribute lookup order One of the things that surprised me recently is that the [[Python language reference http://docs.python.org/reference/]] doesn't seem to document the specifics of how Python searches for the attribute when you try to access _obj.attr_. So here is a not completely formal description of the process for Python 2.7 or so for new-style classes. (Such a description really belongs in the language reference because it's an important part of Python's semantics. It's possible that you can reassemble a full description of the lookup semantics from the bits and pieces scattered throughout the language reference.) First, any time Python looks for an attribute on an object it doesn't just search the object's (nominal) attribute dictionary; it also searches back through the object's base classes (in [[method resolution order MethodResolutionOrder]]), ultimately terminating at _object_. Ordinary instances of classes don't have bases (and can't be given them), but classes do. Let's say we're looking for _attr_ on the object _obj_, and _typ_ is the object's type object (ie _type(obj)_). Then the lookup order is more or less: # if ((typ.attr)) exists and has both a ((__get__)) and either a ((__set__)) or a ((__delete__)) attribute, it's a [[data descriptor http://docs.python.org/reference/datamodel.html#implementing-descriptors]]; we call it and return the result. (Data descriptors thus deliberately preempt attributes on the object itself.) # search for ((obj.attr)). On classes (but not on non-class instances) this may be a descriptor with a ((__get__)) instead of a plain attribute; if it is, it's called. (Classes evaluating their own descriptors is necessary in order to make various descriptor and property things work when you directly access the class. Consider _cls.classmethod()_, for example.) # search for ((typ.attr)). This may be a plain attribute or a non-data descriptor with a ((__get__)); if it's a descriptor, it's called. (As you might guess, the code does not search for ((typ.attr)) twice; it saves the result of the step one search for use in step three.) Note that Python never looks at the type of _typ_; one level into the type hierarchy is as far as it goes. By contrast it will go as far along the base class inheritance hierarchy as it needs to, all the way to _object_ if necessary. (This explains [[how metaclasses can be used to add class-only attributes on classes UsingMetaclass03]]. _instance.attr_ will search only the instance and _cls_, its class, but not go the next step to _type(cls)_, the metaclass. _cls.attr_ will search _cls_ and its base classes (in step 2) and then the metaclass (in step 3).) It's important here to not confuse an object's base classes with its type or its type's base classes. I tend to think of base classes and types as creating a two dimensional structure, where inheritance goes sideways through a class's base classes to end up at _object_ while its type goes up to end up at _type_. Although we often informally talk about instances of an ordinary class inheriting from things and attributes being looked up through them, this is not what is actually happening. A plain instance has no base classes; it is its type (the class it is an instance of) that has the base classes. Normally making this distinction is unimportant, but here it's vital. (The confusing case is a metaclass, which has _type_ as both its base class (since metaclasses subclass _type_) and its type (since all classes, metaclasses included, are normally instances of _type_).) === Sidebar: where this is done in CPython's code In CPython, this is done in two separate pieces of code. Lookups for classes are handled by _type_'s _``type_getattro()''_, in Objects/typeobject.c. Lookups for non-class objects are handled by _object_'s _``PyObject_GenericGetAttrWithDict()''_, in Objects/object.c (which is called with no dictionary argument in this case).