Pythonオブジェクトの文字列表現:strとreprの違いとカスタマイズ方法

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__ を定義することが推奨されます。
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次