Вы можете использовать метод mro
каждого класса, чтобы получить список классов предков. Сопоставьте список предков с collections.Counter
, чтобы на них можно было использовать оператор &
, чтобы получить общих предков при сохранении порядка ключей, эффективно эмулируя получение пересечения упорядоченных множеств. Затем используйте функцию next
для последовательности предков из ключей агрегированного объекта Counter
, чтобы получить самого последнего предка:
from functools import reduce
from operator import and_
from collections import Counter
def lca_type(classes):
return next(iter(reduce(and_, (Counter(cls.mro()) for cls in classes))))
, чтобы все следующие выражения были True
:
lca_type({A, BD}) == A
lca_type({C}) == C
lca_type({B1, B2}) == B
lca_type({B1_1, D}) == A
lca_type({CD, BD}) == D
lca_type({B1_1, BC}) == B1
lca_type({B1_1, BC, BD}) == B
Обратите внимание, что порядок ключей поддерживается только для Python 3.7+, поэтому для предыдущих версий Python вы можете заменить Counter
на подкласс collections.OrderedDict
, который вместо этого использует атрибуты Counter
:
from functools import reduce
from operator import and_
from collections import Counter, OrderedDict
import collections
collections.Counter = Counter = type('Counter', (OrderedDict,), dict(vars(Counter)))
def lca_type(classes):
return next(iter(reduce(and_, (Counter(cls.mro()) for cls in classes))))