Как отсортировать список классов 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'>]