Предварительное примечание: первые три примера обеспечили всю работу. Мой вопрос: если я объявляю классы данных, которые используются только один раз внутри другого класса данных, могу ли я избежать «правильного» объявления вложенного класса данных в пользу «встроенного» объявления?
Я хочу использовать вложенные классы данных, потому что это упрощает доступ к атрибутам в моей 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"
))
Да, первые три решения работают. Однако мне бы хотелось, чтобы мой редактор (я использую VSCode) мог подсказывать мне, какие ключи находятся в объекте, чтобы при вводе my_nested_dataclass.g
отображались параметры .group_1
и .group_2
. Этот вопрос не о правильном или неправильном коде, а об использовании удобной функции подсказок многих редакторов.
А что касается средства проверки типов: я бы хотел, чтобы средство проверки типов знало, что выполнение my_nested_dataclass.group_1 = "bar"
неверно, потому что тип my_nested_dataclass.group_1
равен int
.
Вы пробовали только group_1: Group1 = field(default_factory=Group1)
? Я не понимаю, зачем вам нужно встроенное определение классов данных.
Что не так с вашим кодом «сейчас я делаю это»? Ваши последующие попытки, похоже, связаны с предоставлением значений по умолчанию, например. чтобы вы могли создавать экземпляры без передачи групп типа my_nested_dataclass()
... это то, что вы пытаетесь решить?
в комментариях вы говорите о выполнении my_nested_dataclass.group_1 = "bar"
, но знаете ли вы, что вам нужно создать экземпляр класса данных? Было бы полезно, если бы вы назвали класс в CamelCase в соответствии с соглашениями Python, тогда было бы яснее, что у вас нет экземпляра.
Да, я знаю, что мне нужно создать экземпляр класса данных. Да, я знаю, что мой текущий код работает. Этот вопрос касается исключительно того, могу ли я избежать объявления класса данных, который я использую только один раз, и вместо этого объявить его встроенным. Соответственно уточню вопрос.
Возможно ли иметь встроенное определение класса данных в 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) может добавить или не добавить эту дополнительную поддержку. Вы можете подать запрос на добавление функции, но, по моему опыту, такой запрос, скорее всего, будет отклонен.
Ваше первоначальное решение работает для меня в VS Code с pylance. Какой тип проверки вы используете и в чем заключается ошибка?