Search code examples
pythonmethod-resolution-order

What does "mro()" do?


What does mro() do?


Example from django.utils.functional:

for t in type(res).mro():  # <----- this
    if t in self.__dispatch:
        return self.__dispatch[t][funcname](res, *args, **kw)

Solution

  • Follow along...:

    >>> class A(object): pass
    ... 
    >>> A.__mro__
    (<class '__main__.A'>, <type 'object'>)
    >>> class B(A): pass
    ... 
    >>> B.__mro__
    (<class '__main__.B'>, <class '__main__.A'>, <type 'object'>)
    >>> class C(A): pass
    ... 
    >>> C.__mro__
    (<class '__main__.C'>, <class '__main__.A'>, <type 'object'>)
    >>> 
    

    As long as we have single inheritance, __mro__ is just the tuple of: the class, its base, its base's base, and so on up to object (only works for new-style classes of course).

    Now, with multiple inheritance...:

    >>> class D(B, C): pass
    ... 
    >>> D.__mro__
    (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>)
    

    ...you also get the assurance that, in __mro__, no class is duplicated, and no class comes after its ancestors, save that classes that first enter at the same level of multiple inheritance (like B and C in this example) are in the __mro__ left to right.

    Every attribute you get on a class's instance, not just methods, is conceptually looked up along the __mro__, so, if more than one class among the ancestors defines that name, this tells you where the attribute will be found -- in the first class in the __mro__ that defines that name.