Как получить типы атрибутов объекта класса без его инициализации в Python

Предварительная информация

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

Я пытаюсь создать документацию для этих классов, используя уценку.

Проблема


class BaseParams(JsonObject):
    """ default values for all classes"""

    def __init__(self):
        self.param0: str = "test"


class ExampleParams(BaseParams):
    """ example class for data container"""

    def __init__(self, param1: str):
        super().__init__()
        self.param1: str = param1
        self.param2: int = 0

У меня есть много классов, таких как ExampleParams, в файле py. Я собирал их, их документы и т. Д. Динамически с помощью модулей inspect и importlib, но мне также нужно собрать их параметры и типы параметров.

Пытаюсь получить что-то вроде этого:

resultdict = {
    "ExampleParams":{"param0":"str","param1":"str","param2":"int"}
}

Как я могу сделать это без инициализации классов?

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

PS2: тип каждого атрибута объявляется путем ввода модуля


person obayhan    schedule 13.08.2020    source источник


Ответы (1)


Без инициализации локальные параметры, такие как param0 и param2, не оцениваются, поэтому интерпретатор Python не имеет информации об их существовании или типе.

Единственная возможность, которая у вас есть, - это собрать аргументы метода __init__. Используя ваш пример структуры:

import inspect

params = []
for parent in ExampleParams.mro()[::-1]:
    parent_init = inspect.getfullargspec(parent.__init__)
    # parent_init.annotations contains annotations if specified in method signature
    for param in parent_init.args:
        if param == 'self':
            continue
        params.append(param)

params = ['param1'] в вашем случае.

person ptyshevs    schedule 13.08.2020
comment
Мне также нужно собрать param0, param1 и param 2, иначе это бессмысленно. - person obayhan; 14.08.2020
comment
Вы можете заглянуть в ExampleParams.__init__.__code__, чтобы увидеть всю информацию, которую интерпретатор имеет о __init__. Например, ExampleParams.__init__.__code__.co_names содержит все имена переменных в локальной области. Я думаю, что единственный вариант - написать парсер файлов на Python для извлечения интересующей информации. - person ptyshevs; 14.08.2020
comment
все еще я не могу достичь param0, я думаю, я буду использовать init с помощью paramsclass.__init__.__code__.co_argcount, но получение подсказок типов атрибутов все еще остается - person obayhan; 14.08.2020
comment
В param0 можно попасть только через класс mro. Подсказки типа, опять же, доступны только для аргументов от __init__ до inspect.getfullargspec(ExampleParams.__init__).annotations - person ptyshevs; 14.08.2020
comment
Не совсем то, что я хотел, но похоже, что это единственное решение - person obayhan; 12.10.2020