Возможно ли иметь встроенное определение класса данных в Python?

Предварительное примечание: первые три примера обеспечили всю работу. Мой вопрос: если я объявляю классы данных, которые используются только один раз внутри другого класса данных, могу ли я избежать «правильного» объявления вложенного класса данных в пользу «встроенного» объявления? Я хочу использовать вложенные классы данных, потому что это упрощает доступ к атрибутам в моей IDE, т. е. я хочу иметь возможность использовать точечную запись, например MyNestedDataclass., и моя IDE будет предлагать group_1 и group_2.


Я хочу определить вложенный словарь и использовать функцию Dataclass для точечной записи - главным образом потому, что моя программа проверки типов затем предлагает поля. Это структура данных, к которой я стремлюсь:

my_nested_dict = {
    "group_1": {
        "variable_1a":10,
        "variable_1b":True,
    },
    "group_2": {
        "variable_2a":"foo",
    }
}

В настоящее время я делаю это:

@dataclass
class Group1:
    variable_1a: int = 10
    variable_1b: bool = True

@dataclass
class Group2:
    variable_2a: str = "foo"

@dataclass
class MyNestedDataclass:
    group_1: Group1
    group_2: Group2

Я пробовал этот шаблон, но он приводит к тому, что моя программа проверки типов не знает, какие ключи следует разрешить в MyNestedDataclass.group_1 и MyNestedDataclass.group2, и я не могу получить к нему доступ, например MyNestedDataclass.group_1.variable_1a:

@dataclass
class MyNestedDataclass:
    group_1: dict[str, Any] = field(default_factory=lambda:{
        "variable_1a":10,
        "variable_1b":True,
    })
    group_2: field(default_factory=lambda:{
        "variable_2a":"foo",
    })

Это кажется очень маловероятным, но есть ли что-то вроде этого:

@dataclass
class MyNestedDataclass:
    group_1: Group1 = field(default_factory=lambda: dataclass(
        variable_1a: int = 10
        variable_1b: bool = True
    ))

    group_2: Group2= field(default_factory=lambda: dataclass(
        variable_2a: str = "foo"
    ))

Ваше первоначальное решение работает для меня в VS Code с pylance. Какой тип проверки вы используете и в чем заключается ошибка?

James 24.06.2024 17:34

Да, первые три решения работают. Однако мне бы хотелось, чтобы мой редактор (я использую VSCode) мог подсказывать мне, какие ключи находятся в объекте, чтобы при вводе my_nested_dataclass.g отображались параметры .group_1 и .group_2. Этот вопрос не о правильном или неправильном коде, а об использовании удобной функции подсказок многих редакторов.

Lukas 24.06.2024 17:59

А что касается средства проверки типов: я бы хотел, чтобы средство проверки типов знало, что выполнение my_nested_dataclass.group_1 = "bar" неверно, потому что тип my_nested_dataclass.group_1 равен int.

Lukas 24.06.2024 18:01

Вы пробовали только group_1: Group1 = field(default_factory=Group1) ? Я не понимаю, зачем вам нужно встроенное определение классов данных.

Anentropic 24.06.2024 18:32

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

Anentropic 24.06.2024 18:37

в комментариях вы говорите о выполнении my_nested_dataclass.group_1 = "bar", но знаете ли вы, что вам нужно создать экземпляр класса данных? Было бы полезно, если бы вы назвали класс в CamelCase в соответствии с соглашениями Python, тогда было бы яснее, что у вас нет экземпляра.

Anentropic 24.06.2024 18:40

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

Lukas 25.06.2024 09:35
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
7
77
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Возможно ли иметь встроенное определение класса данных в Python?

Краткий ответ: Нет, не во время проверки типа.

Можно создать класс и, следовательно, класс данных во время выполнения с помощью type():

>>> from dataclasses import dataclass
>>> C = dataclass(type('C', (), {'__annotations__': {'a': int, 'b': str}, 'a': 0, 'b': 'lorem'}))
>>> help(C.__init__)
Help on function __init__ in module __main__:

__init__(self, a: int = 0, b: str = 'lorem') -> None
    Initialize self.  See help(type(self)) for accurate signature.

Однако спецификация не требует наличия средств проверки типов для ее поддержки. Фактически, здесь упоминается только синтаксис, основанный на class.

Средство проверки типов (в вашем случае Pyright) может добавить или не добавить эту дополнительную поддержку. Вы можете подать запрос на добавление функции, но, по моему опыту, такой запрос, скорее всего, будет отклонен.

Другие вопросы по теме