Python のオブジェクトを print() したとき、何が表示されるかを決めるのが __str__ と __repr__ です。どちらも文字列を返すメソッドですが、目的が違う。
何も定義しないとどうなるか
まずデフォルトの挙動を見てみます。
class User: def __init__(self, name, age): self.name = name self.age = age user = User("Alice", 30) print(user) # <__main__.User object at 0x7f...>
クラス名とメモリアドレスが表示される。これでは何のオブジェクトかわからない。
str:人間向けの表現
__str__ は print() や str() で呼ばれます。人間が読むための、わかりやすい文字列を返します。
class User: def __init__(self, name, age): self.name = name self.age = age def __str__(self): return f"{self.name}({self.age}歳)" user = User("Alice", 30) print(user) # Alice(30歳) print(str(user)) # Alice(30歳)
ユーザーに見せる文字列を意識して書く。フォーマットは自由。
repr:開発者向けの表現
__repr__ はオブジェクトの「公式な」文字列表現を返します。デバッグやログ出力で使われることを想定しています。
class User: def __init__(self, name, age): self.name = name self.age = age def __repr__(self): return f"User(name={self.name!r}, age={self.age!r})" user = User("Alice", 30) print(repr(user)) # User(name='Alice', age=30)
慣習として、__repr__ はそのオブジェクトを再現できるような文字列を返すのが理想。eval(repr(obj)) で同じオブジェクトを作れれば完璧ですが、必須ではありません。
両方定義する
通常は両方定義します。
class User: def __init__(self, name, age): self.name = name self.age = age def __str__(self): return f"{self.name}({self.age}歳)" def __repr__(self): return f"User(name={self.name!r}, age={self.age!r})" user = User("Alice", 30) print(user) # Alice(30歳) print(repr(user)) # User(name='Alice', age=30)
人間が読むための表現。print() や str() で呼ばれる。わかりやすさ重視。
開発者がデバッグするための表現。repr() や対話モードで呼ばれる。正確さ重視。
str がないとき repr が使われる
__str__ を定義せず __repr__ だけ定義した場合、print() は __repr__ を使います。
class User: def __init__(self, name, age): self.name = name self.age = age def __repr__(self): return f"User(name={self.name!r}, age={self.age!r})" user = User("Alice", 30) print(user) # User(name='Alice', age=30)(__repr__ が使われる)
逆に __str__ だけ定義して __repr__ を定義しない場合、repr() はデフォルトの <__main__.User object at ...> を返します。
class User: def __init__(self, name, age): self.name = name self.age = age def __str__(self): return f"{self.name}({self.age}歳)" user = User("Alice", 30) print(user) # Alice(30歳) print(repr(user)) # <__main__.User object at 0x7f...>
だから「どちらか一つだけ定義するなら __repr__ を優先せよ」と言われる。__repr__ があれば __str__ のフォールバックとして機能するからです。
コンテナの中では repr が使われる
リストや辞書の中にオブジェクトを入れて表示すると、__repr__ が呼ばれます。
class User: def __init__(self, name): self.name = name def __str__(self): return self.name def __repr__(self): return f"User({self.name!r})" users = [User("Alice"), User("Bob")] print(users) # [User('Alice'), User('Bob')](__repr__ が使われる) for user in users: print(user) # Alice / Bob(__str__ が使われる)
リストの __repr__ が各要素の __repr__ を呼び出している。この挙動を知らないと混乱しがち。
f-string と format での挙動
f-string や format() では __str__ が使われますが、!r を付けると __repr__ を強制できます。
class User: def __init__(self, name): self.name = name def __str__(self): return self.name def __repr__(self): return f"User({self.name!r})" user = User("Alice") print(f"{user}") # Alice(__str__) print(f"{user!r}") # User('Alice')(__repr__) print(f"{user!s}") # Alice(__str__ を明示)
ログ出力では !r を使うと、文字列なのか他の型なのかが明確になって便利です。
name = "Alice" age = 30 # !r なし:型がわからない print(f"name={name}, age={age}") # name=Alice, age=30 # !r あり:文字列は引用符付きで表示される print(f"name={name!r}, age={age!r}") # name='Alice', age=30
実践的な書き方
よくあるパターンをまとめます。
class Point: def __init__(self, x, y): self.x = x self.y = y def __str__(self): return f"({self.x}, {self.y})" def __repr__(self): return f"Point(x={self.x}, y={self.y})" class Person: def __init__(self, name, email): self.name = name self.email = email def __str__(self): return self.name def __repr__(self): return f"Person(name={self.name!r}, email={self.email!r})" class APIResponse: def __init__(self, status, data): self.status = status self.data = data def __str__(self): return f"Status: {self.status}" def __repr__(self): # data が大きい場合は省略 data_repr = repr(self.data) if len(data_repr) > 50: data_repr = data_repr[:50] + "..." return f"APIResponse(status={self.status}, data={data_repr})"
まとめ
デバッグに必須。オブジェクトの状態を正確に表す文字列を返す。__str__ がなければ print() でも使われる。
ユーザー向けの表示が必要なときに。わかりやすさを重視して、技術的な詳細は省いてよい。
迷ったら __repr__ だけ定義すれば十分。両方定義するなら、__repr__ は正確に、__str__ は簡潔に。