Hướng dẫn python convert dataclass to dict - python chuyển đổi dataclass thành dict

Đối với tốc độ thuần khiết, không thay đổi và hiệu quả vô biên, các loại thậm chí có thể khiến những người như Chuck Norris tạm dừng và bất lực nhìn vào sự sợ hãi, tôi khiêm tốn đề xuất cách tiếp cận được lên kế hoạch tốt này với __dict__:pure, unadulterated speed and boundless efficiency, the kinds of which could even cause the likes of Chuck Norris to take pause and helplessly look on in awe, I humbly recommend this remarkably well planned-out approach with __dict__:

def dict(self): _dict = self.__dict__.copy() _dict['message_id'] = str(_dict['message_id']) return _dict

Đối với một lớp xác định thuộc tính __slots__, chẳng hạn như với @dataclass(slots=True), cách tiếp cận trên rất có thể sẽ không hoạt động, vì thuộc tính __dict__ sẽ không có sẵn trên các trường hợp lớp. Trong trường hợp đó, một cách tiếp cận "bắn cho mặt trăng" hiệu quả cao như dưới đây có thể là khả thi:__slots__ attribute, such as with @dataclass(slots=True), the above approach most likely won't work, as the __dict__ attribute won't be available on class instances. In that case, a highly efficient "shoot for the moon" approach such as below could instead be viable:

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)

Trong trường hợp bất kỳ ai đang ở rìa ghế của họ ngay bây giờ (tôi biết, điều này thực sự đáng kinh ngạc, những thứ đột phá) - Tôi đã thêm thời gian cá nhân của mình thông qua mô -đun timeit bên dưới, hy vọng sẽ làm sáng tỏ hơn một chút trong Khía cạnh hiệu suất của mọi thứ.

FYI, các cách tiếp cận với __dict__ thuần túy chắc chắn nhanh hơn nhiều so với 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) 0.

Lưu ý: Mặc dù __dict__ hoạt động tốt hơn trong trường hợp cụ thể này, 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) 0 có thể sẽ tốt hơn cho các từ điển tổng hợp, chẳng hạn như các từ có các dữ liệu lồng nhau hoặc các giá trị có các loại có thể thay đổi như 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) 3 hoặc 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) 4.

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()

Kết quả trên máy tính xách tay Mac M1 của tôi:

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}

Lưu ý: Để thực hiện "hoàn chỉnh" hơn của 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) 5 (được đặt tên là 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) 6), hãy xem một câu trả lời liên quan mà tôi cũng đã thêm.

Chủ đề