dataclass の frozen=True で得られるうれしさ
🐍はじめに
「イミュータブル(frozen=True
)」の嬉しさは一見地味ですが、安心感・バグ防止・設計意図の明示という点でとても頼もしい存在です。それを“読んでいて納得&ワクワク”できる形で、以下に追記します。
🧊 frozen=True
でイミュータブルにすると何が嬉しいの?
from dataclasses import dataclass
@dataclass(frozen=True)
class User:
name: str
age: int
u = User(name="Alice", age=30)
u.age = 31 # ← ここでエラーになる!
frozen=True
をつけると、インスタンスが読み取り専用(イミュータブル)になります。つまり、あとから属性を書き換えようとすると例外(FrozenInstanceError
)が発生します。
🎁 嬉しさ1:設計の意図がハッキリする
「このデータは作ったあと変わらないはずです」というメッセージをコードで伝えられます。
他の人がそのクラスを使うとき、「勝手に値を変えてはダメなんだな」と自然に気づけます。
【成功】→ チーム開発でも安心して使ってもらえる!
🧯 嬉しさ2:思わぬバグを未然に防げる
可変なデータ構造だと、つい user.age += 1
などと書き換えてしまい、「あれ?なんか値が変わってる……?」というバグの温床になります。
イミュータブルにしておけば、意図しない変更は即エラーになって気づけます。
時間を巻き戻すようなバグはデバッグが大変なので、最初から変わらない保証があるととても助かる!
♻️ 嬉しさ3:辞書のキーや集合(set)にも使える
user1 = User(name="Bob", age=40)
my_dict = {user1: "管理者"} # OK!
frozen=True
だと __hash__
が自動実装されるため、辞書のキーやsetの要素として使えるようになります。
普通の dataclass
は可変なので、辞書のキーには使えません。
📐 嬉しさ4:関数型スタイルにマッチする
イミュータブルなオブジェクトは、副作用のない関数と非常に相性が良いです。
「元のオブジェクトは残したまま、新しいオブジェクトを生成する」スタイルが安全でテストしやすい!
def birthday(user: User) -> User:
return User(name=user.name, age=user.age + 1)
こうしておけば「いつの間にか変わってた」を防げて、保守が圧倒的にラクになります。
🧩 まとめ:イミュータブルは“安心設計”のパーツ!
frozen=True
は、単なる「書き換え防止機能」ではありません。
-
設計の意図を明示できる
-
バグの発生を防げる
-
関数型プログラミングとの親和性が高い
-
安心して共有・再利用できる
という点で、読みやすく安全なコードを書くための武器です。
「このオブジェクトは完成品として扱いたいな」と思ったら、迷わずfrozen=True
を付けましょう!