Как вы получаете все классы, определенные в модуле, но не импортированные?

Я уже видел следующий вопрос, но мне это не совсем понятно: Как я могу получить список всех классов в текущем модуле в Python?

В частности, я не хочу импортировать классы, например. если бы у меня был следующий модуль:

from my.namespace import MyBaseClass
from somewhere.else import SomeOtherClass

class NewClass(MyBaseClass):
    pass

class AnotherClass(MyBaseClass):
    pass

class YetAnotherClass(MyBaseClass):
    pass

Если я использую clsmembers = inspect.getmembers(sys.modules[__name__], inspect.isclass), как предполагает принятый ответ в связанном вопросе, он будет возвращать MyBaseClass и SomeOtherClass в дополнение к 3, определенным в этом модуле.

Как я могу получить только NewClass, AnotherClass и YetAnotherClass?

Ответ 1

Осмотреть атрибут __module__ класса, чтобы узнать, в каком модуле он был определен.

Ответ 2

Извиняюсь за ответ на такой старый вопрос, но я не чувствовал себя комфортно, используя модуль проверки для этого решения. Я читал где-то, что было небезопасно для использования в производстве.

Инициализировать все классы в модуле в безымянные объекты в списке

См. комментарий Антониса Кристофидеса к ответу 1.

Я получил ответ для тестирования, если объект является классом из Как проверить, является ли переменная классом или нет?

Итак, это мое неопытное решение

def classesinmodule(module):
    md = module.__dict__
    return [
        md[c] for c in md if (
            isinstance(md[c], type) and md[c].__module__ == module.__name__
        )
    ]

classesinmodule(modulename)

Ответ 3

Вы также можете рассмотреть возможность использования модуля "Python class browser" в стандартной библиотеке: http://docs.python.org/library/pyclbr.html

Поскольку он фактически не выполняет рассматриваемый модуль (вместо этого он использует проверку наивного источника), есть некоторые конкретные методы, которые он не совсем правильно понимает, но для всех "нормальных" определений классов он точно описывает их.

Ответ 4

Я использовал ниже:

# Predicate to make sure the classes only come from the module in question
def pred(c):
    return inspect.isclass(c) and c.__module__ == pred.__module__
# fetch all members of module __name__ matching 'pred'
classes = inspect.getmembers(sys.modules[__name__], pred)

Я не хотел вводить имя текущего модуля в

Ответ 5

from pyclbr import readmodule

clsmembers = readmodule(__name__).items()