Как использовать значение enum в функции asdict из модуля dataclasses - PullRequest
2 голосов
/ 21 апреля 2020

У меня есть класс данных с полем template типа Enum. При использовании функции asdict он преобразует мой класс данных в словарь. Можно ли использовать value атрибут FoobarEnum для возврата строкового значения вместо объекта Enum?

Моя первоначальная идея заключалась в использовании dict_factory=dict параметр функции asdict и укажите собственную фабрику, но я не мог понять, как это сделать.

from dataclasses import dataclass, asdict
from enum import Enum


@dataclass
class Foobar:
  name: str
  template: "FoobarEnum"


class FoobarEnum(Enum):
  FIRST = "foobar"
  SECOND = "baz"


foobar = Foobar(name="John", template=FoobarEnum.FIRST)

print(asdict(foobar))

Токовый выход:

{'name': 'John', 'template': <FoobarEnum.FIRST: 'foobar'>}

Цель:

{'name': 'John', 'template': 'foobar'}

1 Ответ

2 голосов
/ 21 апреля 2020

Это не может быть сделано со стандартной библиотекой, за исключением, возможно, некоторого взлома метакласса enum, о котором я не знаю. Enum.name и Enum.value встроены и не должны изменяться.

Подход с использованием класса данных default_factory также не сработает. Поскольку default_factory вызывается для создания значений по умолчанию для членов класса данных, а не для настройки доступа к членам.

В качестве члена класса данных можно использовать элемент Enum или Enum.value, и вот что asdict() вернусь.

Если вы хотите сохранить элемент Enum, а не просто элемент Enum.value, в качестве члена класса данных, и иметь функцию, преобразующую его в словарь, который возвращает Enum.value вместо элемента Enum, правильный путь сделать это - реализовать собственный метод возврата класса данных в виде словаря.

from dataclasses import dataclass
from enum import Enum


class FoobarEnum(Enum):
    FIRST = "foobar"
    SECOND = "baz"


@dataclass
class Foobar:
    name: str
    template: FoobarEnum

    def as_dict(self):
        return {
            'name': self.name,
            'template': self.template.value
        }


# Testing.
print(Foobar(name="John", template=FoobarEnum.FIRST).as_dict())
# {'name': 'John', 'template': 'foobar'}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...