この記事では、Pythonの__str__と__repr__の使い方を解説します。
自作したクラスをprint関数などで出力したい場合、__str__メソッド、または__repr__メソッドを定義することで実装します。
このような__で囲われた名前のメソッドを「特殊メソッド」や「ダンダーメソッド(ダンダー=ダブルアンダースコアの略)」と言います。
特殊メソッドを定義することでクラスに独自の振る舞いを定義することができます。
Link特殊メソッド名 - データモデル — Python 3.10.4 ドキュメント
それでは、__str__と__repr__の使い方について見ていきましょう!
自作クラスを出力してみる
まずは、自作したクラスをprint関数で出力してみます。
class Person: def __init__(self, name: str, age: int) -> None: self.name = name self.age = age mike = Person('Mike', 20) print(mike)
実行結果
<__main__.Person object at 0x102b33b50>
この値は「__main__で定義されたPersonオブジェクトでアドレスは0x102b33b50です」と出力されたオブジェクトの情報を教えてくれています。
しかし、これではオブジェクトがどのような値を持っているかわかりません。なので、メンバーを知りたい場合は以下のような感じで出力します。
mike = Person('Mike', 20) print(f'name: {mike.name}, age: {mike.age}')
実行結果
name: Mike, age: 20
これでオブジェクトが持っている値を出力することができましたが、値を確認するために毎回上記のようなprint関数を記述するのはとてもめんどくさい。
そんな時に__str__メソッドを定義しておくと楽ちんである。
__str__メソッド
では、先ほどのPersonクラスに__str__メソッドを定義して簡単にオブジェクトの値を出力できるようにしてみましょう!
class Person: def __init__(self, name: str, age: int) -> None: self.name = name self.age = age # ここ def __str__(self) -> str: return f'name: {self.name}, age: {self.age}' mike = Person('Mike', 20) print(mike)
実行結果
name: Mike, age: 20
クラスに__str__メソッドを定義することで、そのオブジェクトに対して文字列が要求された際に返す値を定義することができます。
print関数だけでなく、例えばオブジェクトをフォーマットする際にも文字列を要求するので__str__メソッドの値が渡されます。
mike = Person('Mike', 20) print('format {}'.format(mike)) print(f'フォーマット済み文字列リテラル {mike}')
実行結果
format name: Mike, age: 20 フォーマット済み文字列リテラル name: Mike, age: 20
ということで自作クラスを出力する際に便利な__str__メソッドでした。
__repr__メソッド
では次に__repr__メソッドについて見ていきましょう!
__repr__メソッドには、同じ値のオブジェクトを再生成できる文字列を定義します。
同じ値のオブジェクトを再生成できる文字列とは、例えば、mike = Person('Mike', 20)と生成されたオブジェクトならばPerson('Mike', 20)の部分のことを言います。
実際に実装すると以下のような感じになります。
class Person: def __init__(self, name: str, age: int) -> None: self.name = name self.age = age def __repr__(self) -> str: return f"Person(name='{self.name}', age={self.age})"
__repr__はrepr関数で呼び出すことができる。
mike = Person('Mike', 20) print(repr(mike))
実行結果
Person(name='Mike', age=20)
実際に同じオブジェクトが生成できるかどうかはeval関数を使って検証できます。eval関数は、引数で指定された文字列をソースコードとして実行します。
mike = Person('Mike', 20) m = eval(repr(mike)) print(m)
実行結果
Person(name='Mike', age=20)
mが出力された際にmikeと同等の__repr__の値を返しました。eval関数と__repr__の値を用いて同じ値を持つオブジェクトを再生成できました。
__str__が定義されていない場合に文字列が要求されたら__repr__の値が返されます。
もっと動的に__repr__を生成したい場合は、以下のような定義で実装できます。
def __repr__(self) -> str: mem = [f"{key}={value!r}" for key, value in self.__dict__.items()] return f"{self.__class__.__name__}({', '.join(mem)})"
__str__と__repr__の違い
__str__は、print関数などで文字列を要求された場合に返す値を定義、__repr__は、eval関数でオブジェクトを再生成できる文字列を定義します。
文字列を返す点では同じですが用途は全く違いますね。
なぜこの2つのメソッドが混同されやすいかというとprint関数などで文字列を要求された際に__str__が定義されていない場合は__repr__の値が返されてしまうのが原因だと考えます。
混同しないように注意してください。
まとめ
この記事では、Pythonの__str__と__repr__の使い方を解説しました。
__str__は、文字列が要求された際に返したい値を定義し、__repr__では、eval関数で同じ値のオブジェクトが再生成できる文字列を定義します。
一度覚えてしまえば簡単ですね。
それでは今回の内容はここまでです。ではまたどこかで〜( ・∀・)ノ


