Skip to content

Python dataclass を文字列リテラルの辞書に変換する方法

Python の dataclass を辞書に変換する際、特定のフィールド(特に UUID など)を文字列リテラルとして表現したい場合があります。この記事では、効率的で適切な方法をいくつか紹介します。

問題点

以下のような dataclass がある場合:

python
from dataclasses import dataclass
import uuid

@dataclass
class MessageHeader:
    message_id: uuid.UUID

単純に辞書化すると、message_id フィールドは UUID オブジェクトのままになります:

python
header = MessageHeader(message_id=uuid.uuid4())
print(header.__dict__)
# {'message_id': UUID('383b0bfc-743e-4738-8361-27e6a0753b5a')}

しかし、以下のように文字列リテラルとして表現したい場合があります:

python
{'message_id': '383b0bfc-743e-4738-8361-27e6a0753b5a'}

解決方法

方法 1: シンプルな辞書内包表記

最もシンプルで読みやすい方法です:

python
from dataclasses import dataclass, asdict
import uuid

@dataclass
class MessageHeader:
    message_id: uuid.UUID
    
    def to_dict(self):
        return {k: str(v) for k, v in asdict(self).items()}

使用例:

python
header = MessageHeader(message_id=uuid.uuid4())
result = header.to_dict()
print(result)
# {'message_id': '383b0bfc-743e-4738-8361-27e6a0753b5a'}

TIP

asdict() はネストした dataclass や複合データ構造も正しく処理しますが、パフォーマンスが若干低下する可能性があります。

方法 2: __dict__ を直接使用(高速)

パフォーマンスが重要な場合:

python
@dataclass
class MessageHeader:
    message_id: uuid.UUID
    
    def to_dict(self):
        result = self.__dict__.copy()
        result['message_id'] = str(result['message_id'])
        return result

WARNING

この方法は __slots__ を使用しているクラスでは動作しないことに注意してください。

方法 3: 条件付き変換

複数のフィールドを条件付きで変換する場合:

python
@dataclass
class MessageHeader:
    message_id: uuid.UUID
    count: int
    
    def to_dict(self):
        return {
            k: str(v) if isinstance(v, uuid.UUID) else v
            for k, v in self.__dict__.items()
        }

方法 4: __slots__ を使用する場合

@dataclass(slots=True) を使用している場合:

python
@dataclass(slots=True)
class MessageHeader:
    message_id: uuid.UUID
    count: int
    
    def to_dict(self):
        return {
            'message_id': str(self.message_id),
            'count': self.count
        }

パフォーマンス比較

各方法のパフォーマンス比較(10,000回実行した場合の時間):

方法実行時間(秒)
__dict__ 直接使用約 0.006
辞書内包表記約 0.008
dataclasses.asdict() 使用約 0.071

INFO

単純な変換には __dict__ を直接操作する方法が最も高速ですが、asdict() はより複雑なデータ構造を適切に処理します。

まとめ

Python dataclass を文字列リテラルの辞書に変換するには、以下の方法がおすすめです:

  1. シンプルで読みやすい場合: asdict() を使用した辞書内包表記
  2. パフォーマンス重視の場合: __dict__ を直接操作
  3. __slots__ 使用時: 明示的に各フィールドを変換

用途に応じて最適な方法を選択してください。データ構造が複雑な場合は asdict() を、シンプルでパフォーマンスが重要な場合は __dict__ の直接操作を推奨します。