Как отсортировать список классов Python по глубине наследования?

Как бы я отсортировал список классов в Python, убедившись, что любой дочерний класс находится перед любым из его родительских классов в списке?

Я спрашиваю, потому что я хочу увидеть, какому типу из списка типов принадлежит объект, но найти наиболее конкретный тип, если он принадлежит множеству.

2 ответа

Решение

Просто сортировать по len(cls.mro()),

Если C2 это подкласс C1, он должен держать это len(C1.mro()) < len(C2.mro()) (потому что каждый класс в C1.mro() также должен появиться в C2.mro()). Для этого вы можете просто отсортировать по длине списка mro:

class A(object): pass
class X(object): pass
class B(A, X): pass
class C(B): pass
class D(C): pass

sorted([B, C, A, D, X], key = lambda cls: len(cls.mro()))
=> [__main__.A, __main__.X, __main__.B, __main__.C, __main__.D]

Чтобы также поддерживать классы старого стиля, вы можете заменить cls.mro() с inspect.getmro(cls),

Лучшим подходом было бы использовать набор, а затем перемещаться по дереву наследования целевого класса.

def find_parent(target, class_set):
    if target in class_set:
        return [target]
    else:
        bases = []
        for parent in target.__bases__:
            result = find_parent(parent, class_set)
            if result is not None:
                bases.extend(result)
        return bases

Пример:

class A(object):
    pass

class B(str):
    pass

class C(A):
    pass

class D(A, dict):
    pass

class_set = {dict, A}

print find_parent(A, class_set)
print find_parent(B, class_set)
print find_parent(C, class_set)
print find_parent(D, class_set)

Дает вам этот результат:

[<class '__main__.A'>]
[]
[<class '__main__.A'>]
[<class '__main__.A'>, <type 'dict'>]
Другие вопросы по тегам