Pythonで独自のクラスを定義し、そのインスタンスを print() 関数で出力すると、デフォルトでは <__main__.ClassName object at 0x...> のような、人間には理解しづらい内部情報(メモリアドレス)が表示されます。
デバッグやログ出力の際に、オブジェクトの中身(属性の値など)をわかりやすく表示させるには、特殊メソッドである __str__ と __repr__ を定義する必要があります。
この記事では、これら2つのメソッドの役割の違いと、具体的な実装方法について解説します。
デフォルトの動作(メソッド未定義の場合)
まず、これらのメソッドを定義していない場合の挙動を確認します。例として、書籍データを管理する Book クラスを作成します。
class Book:
def __init__(self, title, author, price):
self.title = title
self.author = author
self.price = price
# インスタンス化
my_book = Book("Python入門", "山田太郎", 2800)
# print() で出力
print(f"print出力: {my_book}")
実行結果:
print出力: <__main__.Book object at 0x000001A2B3C4D5E6>
このように、オブジェクトの種類とメモリアドレスが表示されるだけで、どの本なのか判別できません。
1. __str__ メソッド:利用者向けの表現
__str__ メソッドは、オブジェクトの「利用者にとって読みやすい文字列表現」を定義するために使用します。
主に以下の場面で呼び出されます。
print()関数に渡されたときstr()関数で文字列に変換されたとき- f-string や
format()メソッドで文字列に埋め込まれたとき
class Book:
def __init__(self, title, author, price):
self.title = title
self.author = author
self.price = price
def __str__(self):
# 利用者が見やすい形式(タイトルと著者名など)を返す
return f"『{self.title}』 著:{self.author} ({self.price}円)"
my_book = Book("Python入門", "山田太郎", 2800)
print(f"__str__の出力: {my_book}")
実行結果:
__str__の出力: 『Python入門』 著:山田太郎 (2800円)
print() の結果が、人間にとって理解しやすい形式に変わりました。
2. __repr__ メソッド:開発者向けの表現
__repr__ メソッドは、オブジェクトの「開発者にとって厳密で曖昧さのない文字列表現」を定義するために使用します。
理想的には、その文字列を eval() 関数で実行すれば、元のオブジェクトを復元できるような形式(コードとしての文字列表現)を返すことが推奨されます。
主に以下の場面で呼び出されます。
repr()関数に渡されたとき- インタラクティブシェル(対話モード)で変数名を入力してEnterを押したとき
- リストや辞書の中にオブジェクトが含まれている状態で、そのリスト等を表示したとき
__str__が定義されていない場合のバックアップとして
class Book:
def __init__(self, title, author, price):
self.title = title
self.author = author
self.price = price
def __repr__(self):
# 開発者向け:オブジェクトを再生成できるような形式を返す
return f"Book(title='{self.title}', author='{self.author}', price={self.price})"
my_book = Book("Python入門", "山田太郎", 2800)
# repr() 関数を使って呼び出す
print(f"__repr__の出力: {repr(my_book)}")
実行結果:
__repr__の出力: Book(title='Python入門', author='山田太郎', price=2800)
__str__ と __repr__ の併用と使い分け
両方のメソッドを定義した場合の挙動と、リスト内での表示について確認します。
class Book:
def __init__(self, title, author, price):
self.title = title
self.author = author
self.price = price
def __str__(self):
return f"書籍: {self.title}"
def __repr__(self):
return f"Book('{self.title}', '{self.author}', {self.price})"
book1 = Book("AIの未来", "佐藤次郎", 3500)
book2 = Book("統計学の基礎", "鈴木花子", 2200)
print("1. print(book1) の場合 (__str__が優先):")
print(book1)
print("\n2. print(repr(book1)) の場合 (__repr__を指定):")
print(repr(book1))
print("\n3. リストに入れた場合 (リスト内の要素は __repr__ で表示される):")
book_list = [book1, book2]
print(book_list)
実行結果:
1. print(book1) の場合 (__str__が優先):
書籍: AIの未来
2. print(repr(book1)) の場合 (__repr__を指定):
Book('AIの未来', '佐藤次郎', 3500)
3. リストに入れた場合 (リスト内の要素は __repr__ で表示される):
[Book('AIの未来', '佐藤次郎', 3500), Book('統計学の基礎', '鈴木花子', 2200)]
重要なポイント: リストや辞書などのコレクションにオブジェクトを格納して print した場合、要素であるオブジェクトは __str__ ではなく __repr__ を使って表示されます。これはデバッグ時に中身を正確に把握するためです。
まとめ
__str__: エンドユーザー向け。print()で表示される読みやすい文字列。__repr__: 開発者(デバッグ)向け。repr()で表示される厳密な文字列。リストの中身を表示する際にも使われる。- 実装の指針として、少なくとも
__repr__を実装しておけば、__str__がない場合の代わりとしても機能するため、まずは__repr__を定義することが推奨されます。
