Unk*_*own 57 python json dictionary python-dataclasses
给定如下数据类:
class MessageHeader(BaseModel):
message_id: uuid.UUID
def dict(self, **kwargs):
return json.loads(self.json())
Run Code Online (Sandbox Code Playgroud)
dict当我调用时,我想获得一个字符串文字的字典。MessageHeader
字典的期望结果如下所示:
{'message_id': '383b0bfc-743e-4738-8361-27e6a0753b5a'}
Run Code Online (Sandbox Code Playgroud)
我想避免使用第三方库,例如pydantic& 我不想使用json.loads(self.json()),因为有额外的往返
有没有更好的方法将数据类转换为带有上面字符串文字的字典?
Mad*_*ist 83
您可以使用dataclasses.asdict:
from dataclasses import dataclass, asdict
class MessageHeader(BaseModel):
message_id: uuid.UUID
def dict(self):
return {k: str(v) for k, v in asdict(self).items()}
Run Code Online (Sandbox Code Playgroud)
如果您确定您的类只有字符串值,您可以完全跳过字典理解:
class MessageHeader(BaseModel):
message_id: uuid.UUID
dict = asdict
Run Code Online (Sandbox Code Playgroud)
rv.*_*tch 16
对于绝对纯粹、纯粹的速度和无限的效率,这些甚至可能导致像 Chuck Norris 这样的人停下来,无助地敬畏地看着,我谦虚地推荐这种精心策划的方法__dict__:
def dict(self):
_dict = self.__dict__.copy()
_dict['message_id'] = str(_dict['message_id'])
return _dict
Run Code Online (Sandbox Code Playgroud)
__slots__对于定义attribute的类(例如 with @dataclass(slots=True)),上述方法很可能不起作用,因为该__dict__属性在类实例上不可用。在这种情况下,如下所示的高效“登月”方法可能是可行的:
def dict(self):
body_lines = ','.join(f"'{f}':" + (f'str(self.{f})' if f == 'message_id'
else f'self.{f}') for f in self.__slots__)
# Compute the text of the entire function.
txt = f'def dict(self):\n return {{{body_lines}}}'
ns = {}
exec(txt, locals(), ns)
_dict_fn = self.__class__.dict = ns['dict']
return _dict_fn(self)
Run Code Online (Sandbox Code Playgroud)
万一有人现在在座位边缘摇摇欲坠(我知道,这真的是令人难以置信的突破性的东西) - 我已经通过timeit下面的模块添加了我的个人计时,这应该有望在性能上提供更多的启示事物的方面。
仅供参考,使用 pure 的方法__dict__不可避免地比dataclasses.asdict().
注意:尽管
__dict__在这种特殊情况下效果更好,dataclasses.asdict()但对于复合字典可能会更好,例如具有嵌套数据类的字典,或具有可变类型(例如dict或 )的值list。
from dataclasses import dataclass, asdict, field
from uuid import UUID, uuid4
class DictMixin:
"""Mixin class to add a `dict()` method on classes that define a __slots__ attribute"""
def dict(self):
body_lines = ','.join(f"'{f}':" + (f'str(self.{f})' if f == 'message_id'
else f'self.{f}') for f in self.__slots__)
# Compute the text of the entire function.
txt = f'def dict(self):\n return {{{body_lines}}}'
ns = {}
exec(txt, locals(), ns)
_dict_fn = self.__class__.dict = ns['dict']
return _dict_fn(self)
@dataclass
class MessageHeader:
message_id: UUID = field(default_factory=uuid4)
string: str = 'a string'
integer: int = 1000
floating: float = 1.0
def dict1(self):
_dict = self.__dict__.copy()
_dict['message_id'] = str(_dict['message_id'])
return _dict
def dict2(self):
return {k: str(v) if k == 'message_id' else v
for k, v in self.__dict__.items()}
def dict3(self):
return {k: str(v) if k == 'message_id' else v
for k, v in asdict(self).items()}
@dataclass(slots=True)
class MessageHeaderWithSlots(DictMixin):
message_id: UUID = field(default_factory=uuid4)
string: str = 'a string'
integer: int = 1000
floating: float = 1.0
def dict2(self):
return {k: str(v) if k == 'message_id' else v
for k, v in asdict(self).items()}
if __name__ == '__main__':
from timeit import timeit
header = MessageHeader()
header_with_slots = MessageHeaderWithSlots()
n = 10000
print('dict1(): ', timeit('header.dict1()', number=n, globals=globals()))
print('dict2(): ', timeit('header.dict2()', number=n, globals=globals()))
print('dict3(): ', timeit('header.dict3()', number=n, globals=globals()))
print('slots -> dict(): ', timeit('header_with_slots.dict()', number=n, globals=globals()))
print('slots -> dict2(): ', timeit('header_with_slots.dict2()', number=n, globals=globals()))
print()
dict__ = header.dict1()
print(dict__)
asdict__ = header.dict3()
print(asdict__)
assert isinstance(dict__['message_id'], str)
assert isinstance(dict__['integer'], int)
assert header.dict1() == header.dict2() == header.dict3()
assert header_with_slots.dict() == header_with_slots.dict2()
Run Code Online (Sandbox Code Playgroud)
我的 Mac M1 笔记本电脑上的结果:
dict1(): 0.005992999998852611
dict2(): 0.00800508284009993
dict3(): 0.07069579092785716
slots -> dict(): 0.00583599996753037
slots -> dict2(): 0.07395245810039341
{'message_id': 'b4e17ef9-1a58-4007-9cef-39158b094da2', 'string': 'a string', 'integer': 1000, 'floating': 1.0}
{'message_id': 'b4e17ef9-1a58-4007-9cef-39158b094da2', 'string': 'a string', 'integer': 1000, 'floating': 1.0}
Run Code Online (Sandbox Code Playgroud)
注意:DictMixin对于(命名为)的更“完整”实现SerializableMixin,请查看我还添加的相关答案。
这是“dataclass to dict”的最佳谷歌结果,上面的答案过于复杂。您可能正在寻找这个:
from dataclasses import dataclass
@dataclass
class MessageHeader():
uuid: str = "abcd"
vars(MessageHeader()) # or MessageHeader().__dict__
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
75060 次 |
| 最近记录: |