如何在数据类模块的 asdict 函数中使用枚举值

Nep*_*nat 11 python enums python-dataclasses

我有一个字段template类型为 Enum的数据类。使用该asdict函数时,它将我的数据类转换为字典。是否可以使用valueof 属性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))
Run Code Online (Sandbox Code Playgroud)

电流输出:

{'name': 'John', 'template': <FoobarEnum.FIRST: 'foobar'>}
Run Code Online (Sandbox Code Playgroud)

目标:

{'name': 'John', 'template': 'foobar'}
Run Code Online (Sandbox Code Playgroud)

小智 11

我遇到了类似的问题,我需要将数据类对象序列化为 JSON,并通过添加str作为第一个类 FoobarEnum 继承来解决它:

import json
from dataclasses import dataclass, asdict
from enum import Enum


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


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


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

print(json.dumps(asdict(foobar)))
Run Code Online (Sandbox Code Playgroud)

它不会改变 的行为asdict,但我现在可以序列化该对象。

参考:将 Enum 成员序列化为 JSON


小智 9

其实你可以做到。asdict有关键字参数dict_factory允许你在那里处理你的数据:

from dataclasses import dataclass, asdict
from enum import Enum


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


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


def custom_asdict_factory(data):

    def convert_value(obj):
        if isinstance(obj, Enum):
            return obj.value
        return obj

    return dict((k, convert_value(v)) for k, v in data)


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

print(asdict(foobar, dict_factory=custom_asdict_factory))
# {'name': 'John', 'template': 'foobar'}
Run Code Online (Sandbox Code Playgroud)


bad*_*der 7

这不能用标准库来完成,除非可能是通过我不知道的一些元类枚举黑客。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'}

Run Code Online (Sandbox Code Playgroud)


Evg*_*din 5

from dataclasses import dataclass, asdict
from enum import Enum


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


@dataclass
class Foobar:
    name: str
    template: FoobarEnum


def my_dict(data):

    return {
        field: value.value if isinstance(value, Enum) else value
        for field, value in data
    }


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

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

assert asdict(foobar, dict_factory=my_dict) == data
Run Code Online (Sandbox Code Playgroud)