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,但我现在可以序列化该对象。
小智 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)
这不能用标准库来完成,除非可能是通过我不知道的一些元类枚举黑客。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)
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)