Python: определить базовый класс class_object - PullRequest
0 голосов
/ 04 июля 2018

У меня есть следующий код:

if __name__ == '__main__':

module_name = sys.argv[1]
is_lite = sys.argv[2]

importlib.import_module(module_name)

for name, class_object in inspect.getmembers(sys.modules[module_name]):
    if inspect.isclass(class_object) and not inspect.isabstract(class_object):

        try:
            print "\n\n\n"
            print "Executing: "
            print class_object
            print "\n\n\n"

            instance = class_object()
            instance.execute(is_lite)
        except:
            pass

Все объекты, которые будут созданы, на самом деле являются подклассами класса с именем: Foo, который является абстрактным.

Возвращаемые функцией inspect класс_объекты содержат ВСЕ классы, содержащиеся в модуле, это означает, что импорт также присутствует в списке, а импорт не является подклассом Foo.

class_object

То, что я ищу, это просто метод получения следующей информации:

is (class_object, Foo)

Это позволило бы мне избавиться от ловушки try и получить более логичный и надежный код.

Но пока я ничего не нашел, кажется, нет простого способа извлечь информацию, содержащуюся в модулях, возвращаемых платформой inspect.

Я также пытался использовать встроенный метод issubclass, но он ошибочен, вероятно, потому, что class_object не является экземпляром класса, а просто его описателем: class_object является экземпляром abc.ABCMeta, а не Foo, но будет содержать всю информацию о Фу.

Спасибо за помощь.

Ответы [ 3 ]

0 голосов
/ 04 июля 2018

Вам даже не нужно использовать модуль inspect.

Этого легко добиться, проверив атрибут __bases__ для class:

class Foo(object):
    pass

class Bar(Foo):
    pass

print('Bar is child of Foo?', Foo in Bar.__bases__)

__bases__ однако, показывает только прямого родителя данного класса, а не всего предка.

На самом деле вы можете реализовать это самостоятельно, перебирая всю цепочку базовых предложений и объединяя их в один кортеж:

def get_all_bases(cls, bases=None):
     bases = bases or []
     bases.append(cls)
     for c in cls.__bases__:
         get_all_bases(c, bases)
     return tuple(bases)

Тогда вы просто:

class Foo(object):
   pass

class Bar(Foo):
   pass

class FooBar(Bar):
   pass

print('FooBar is child of Foo?', Foo in get_all_bases(FooBar))
0 голосов
/ 11 июля 2018

Пока что я не нашел ничего другого, кроме как сделать это так:

importlib.import_module(module_name)

for _, class_object in inspect.getmembers(sys.modules[module_name]):
    if inspect.isclass(class_object) and not inspect.isabstract(class_object):

        instance = None

        try:
            instance = class_object()

        except:
            pass

        if instance is not None and isinstance(instance, AbstractBaseClass):
            instance.execute(is_lite)

Я не нашел простого способа разобрать содержимое 'class_object' и извлечь строку, представляющую имя класса объекта.

Для информации 'class_object' возвращает что-то вроде этого

<class 'name of the actual class'>
   classAttribute: value of the attribute
   ...
   classMethod: <unbound method 'className'.'methodName'>
   ...
   _abc_various_metadatas
0 голосов
/ 04 июля 2018

Взгляните на Python Reflections , который может предоставить информацию о типе, классе, атрибутах и ​​методах объекта.

Вы ищете

isinstance(inspect, class_object)

Множественные проверки будут дополнительно определять наследование

...