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

Я уже видел следующий вопрос, но он меня не совсем понимает, где я хочу: Как получить список всех классов в текущем модуле 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?


person Davy8    schedule 02.04.2011    source источник
comment
Если я не ошибаюсь, не отвечают ли комментарии к принятому ответу в этом вопросе на ваш вопрос? (Я не пробовал проверять, работает ли это)   -  person zxt    schedule 02.04.2011
comment
@zxt d'oh не обращал внимания на комментарии. Вы правы, это отвечает на мой вопрос.   -  person Davy8    schedule 02.04.2011


Ответы (5)


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

person Ignacio Vazquez-Abrams    schedule 02.04.2011
comment
Понимание списка по строкам [m for m in clsmembers if m[1].__module__ == 'mymodule'] должно помочь. Вы также можете указать лямбда-функцию в качестве предиката для вызова inspect.getmembers(), как показано в упомянутом вами вопросе. - person Blair; 02.04.2011

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

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

См. комментарий Антониса Кристофидеса ответить 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)
person piRSquared    schedule 04.02.2014
comment
Всегда перебирайте элементы, если вам нужны и то, и другое: v for c,v in md.iteritems() if ( isinstance(v, type) and v.__module__ == module.__name__ ) - person Mr_and_Mrs_D; 04.06.2016

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

Поскольку он на самом деле не выполняет рассматриваемый модуль (вместо этого он выполняет наивную проверку источника), существуют некоторые конкретные методы, которые он не совсем правильно понимает, но для всех «нормальных» определений классов он будет описывать их точно.

person ncoghlan    schedule 02.04.2011

Я использовал следующее:

# 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)

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

person rmc    schedule 11.11.2011

person    schedule
comment
Хотя этот код может решить проблему, всегда полезно добавить к нему объяснение. - person BDL; 19.01.2017