この記事では、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
関数で同じ値のオブジェクトが再生成できる文字列を定義します。
一度覚えてしまえば簡単ですね。
それでは今回の内容はここまでです。ではまたどこかで〜( ・∀・)ノ