2013-10-14 4 views
2

Как найти все абстрактные базовые классы, которые данный класс является «виртуальным подклассом»?Найти все абстрактные базовые классы, которые зарегистрированы классом с помощью

Другими словами, я ищу волшебную функцию virtual_base_classes(), что делает что-то вроде этого:

>>> for cls in virtual_base_classes(list): 
>>> print(cls) 
<class 'collections.abc.MutableSequence'> 
<class 'collections.abc.Sequence'> 
<class 'collections.abc.Sized'> 
<class 'collections.abc.Iterable'> 
<class 'collections.abc.Container'> 

(я не знаю, все abc классы, list зарегистрирован, поэтому в приведенном выше примере может быть неполным.)

Обратите внимание, что не каждый абстрактный базовый класс будет определен в collections.abc. Существует модуль abc (отличный от collections.abc), который обеспечивает метакласс ABCMeta. Любой класс, являющийся экземпляром ABCMeta, поддерживает регистрацию «виртуальных подклассов» с использованием стандартного интерфейса (метод register). Ничто не мешает кому-либо (программисту или библиотеке Python) создавать экземпляр ABCMeta, который не принадлежит collections.abc.

+1

класс «не знает», что он был зарегистрирован в качестве виртуального подкласса некоторого ABC, так что вы не можете найти всю азбуку, начиная с класса , Между тем, Python не предоставляет средства для поиска каждого класса, у которого 'ABCMeta' является его метаклассом (если только не существует частичной интроспекции, которую вы можете найти, чтобы найти все классы, в том числе те, чей модуль больше не находится в' sys.modules' из-за к перезагрузке модуля). Таким образом, вы не можете найти все ABC вашего типа, начиная с списка всех существующих ABC. –

+0

@SteveJessop спасибо, это имеет смысл. Я предполагаю, что, строго говоря, я могу найти все доступные классы, итерации через фреймы стека, - но я не хотел идти так далеко. – max

+0

Хе-хе, да, с достаточным усилием вы могли бы перебирать все объекты в среде исполнения Python, тестируя каждый поочередно, чтобы узнать, является ли это ABC, и если да, то какой целевой тип 'issubclass'. –

ответ

3

Использование issubclass и список понимание:

>>> import collections.abc 
>>> import inspect 
>>> [v for k, v in vars(collections.abc).items() 
            if inspect.isclass(v) and issubclass(list, v) ] 
[<class 'collections.abc.Container'>, 
<class 'collections.abc.Sequence'>, 
<class 'collections.abc.MutableSequence'>, 
<class 'collections.abc.Iterable'>, 
<class 'collections.abc.Sized'> 
] 
+0

Извините, мне нужен список всех абстрактных базовых классов - вместо того, чтобы проверять один за другим. Я уточню в вопросе. – max

+0

@max обновил ответ. –

+0

Спасибо. Это будет работать для 'collections.abc', но не в целом. Я обновляю вопрос, чтобы объяснить, поскольку в комментарии недостаточно места. – max