pythonpython-3.xclassmetaclassmethod-resolution-order

How to recover the mro of a class given its bases?


Suppose we are implementing a metaclass that needs to know the method resolution order before the class is instantiated.

class Meta(type):
    def __new__(cls, name, bases, namespace):
        mro = ...

Is there a builtin way to compute the mro, that is a way other than reimplementing the C3 algorithm?


Solution

  • It turns out the functools module has a _c3_merge function that implements the C3 linearization algorithm:

    import functools
    
    def compute_mro(*bases):
      return functools._c3_merge(base.mro() for base in bases)
    
    # Example:
    class F: pass
    
    class E: pass
    
    class D: pass
    
    class C(D,F): pass
    
    class B(D,E): pass
    
    class A(B,C): pass
    
    print(compute_mro(B, C)) # [B, C, D, E, F, object]
    
    print(A.mro()) # [A, B, C, D, E, F, object]