A simplified summary of Python's method resolution order

February 22, 2007

Crudely summarized, method resolution order is how Python decides where to look for a method (or any other attribute) on a class that inherits from several classes. Python actually has two; a simple one for old style classes and a rather complicated one for new style classes.

(Technically, method resolution order applies even for single inheritance classes, it's just that they have a very boring one.)

With the old style class:

class Foo(A, B, C):
    pass

Python will look up Foo.foo by looking for foo on A and all of its ancestors, then B and all its ancestors, and finally C and all its ancestors; that is, the method resolution order is left to right, depth first.

This order is nice and simple but blows up if A and B have a common ancestor with behavior that B wants to override, which is why new style classes need a different scheme. (All new style classes are ultimately rooted at object, which defines various default actions for things like getting and setting attributes.)

The complete description of the method resolution order for new style classes is somewhat complicated. For simple class structures, it can be summarized as left to right and depth first but common ancestor classes are only checked after all of their children have been checked. Thus, with new style classes:

class A1(object):       pass
class A2(object):       pass
class A3(object):       pass
class B2(A2):           pass
class B3(A3):           pass
class C3(B3):           pass
class Foo(C3, A1, B2):  pass

The method resolution order for Foo.foo is Foo, C3, B3, A3, A1, B2, A2, and then object; as the common ancestor, object is checked only after all of its children have been. Note that the MRO can vary drastically between a parent and a child class; C3's MRO is just C3, B3, A3, and object.

In case of doubt or curiosity you can find the MRO of any new style class in its __mro__ attribute. Normally you don't need to care about its value and should use the super() builtin if you need to find the next class up in the context of a particular object or class.

(This is the kind of entry I write partly to make sure I have all this straight in my own head.)

Written on 22 February 2007.
« My zeroth law of compromised machines
The downside of distinctive hostnames »

Page tools: View Source, Add Comment.
Search:
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Thu Feb 22 23:22:06 2007
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.