Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonのstr()とrepr()の違いとは?使い分けのポイントを徹底解説

Pythonのstr()repr()は、どちらもオブジェクトを文字列として表現するためのメソッドです。一見すると同じ役割を果たしているように見えますが、実は両者には重要な違いが存在します。

Pythonの組み込み関数str(x)(xは任意のオブジェクト)を呼び出したとき、内部で何が起こっているのか考えたことはありますか?実はstr(x)の戻り値は2つの特殊メソッドによって決まります。まず__str__が優先的に呼ばれ、定義されていない場合には__repr__がフォールバックとして使用される仕組みです。

公式ドキュメントでの定義

まず、Pythonの公式ドキュメントがこれらの関数について何を説明しているか見てみましょう。

>>> help(str)
Help on class str in module builtins:

class str(object)
| str(object='') -> str
| str(bytes_or_buffer[, encoding[, errors]]) -> str
|
| Create a new string object from the given object.

>>> help(repr)
Help on built-in function repr in module builtins:

repr(obj, /)
Return the canonical string representation of the object.

For many object types, including most builtins, eval(repr(obj)) == obj.

repr()の説明に「eval(repr(obj)) == obj」とある点がポイントです。これが両者の違いを理解する鍵となります。

基本的な使用例

それでは、いくつかの具体例を使って2つのメソッドの挙動を確認していきましょう。

>>> str(123)
'123'
>>> repr(123)
'123'
>>> # 上記の通り、整数データでは2つのメソッドに違いはない
>>> # 次に、文字列データでこの2つのメソッドを試してみる
>>> str('Python')
'Python'
>>> repr('Python')
"'Python'"

整数値に対してはrepr()とstr()の戻り値はまったく同じですが、文字列に対しては結果が異なります。一方は「形式的(フォーマル)」な表現であり、もう一方は「非形式的(インフォーマル)」な表現なのです。

公式ドキュメントによると、__str__はオブジェクトの「非形式的(読みやすい)」文字列表現を取得するために使われ、一方__repr__はオブジェクトの「形式的(公式)」な文字列表現を取得するために使われます。

eval()との関係から見る違い

形式的表現と非形式的表現の最も重要な違いは、str値に対する__repr__のデフォルト実装の戻り値を、eval()の引数として渡せるという点です。eval()は文字列を受け取り、その内容をPythonコードとして評価する組み込み関数です。

つまり、repr()の結果である「'Python'」をeval()に渡すと正常に動作します。しかし、str()の結果である「Python」を渡すとエラーになります。これは、引用符のない「Python」が未定義の変数として解釈されるためです。以下のコードで確認してみましょう。

>>> x = "Python"
>>> repr(x)
"'Python'"
>>> x1 = eval(repr(x))
>>> x == x1
True

このように、__repr__の戻り値をeval()に渡すと、元のオブジェクトと等価な値を復元できます。

一方、__str__の戻り値をeval()の引数として渡すと失敗します。

>>> y = "Python"
>>> str(y)
'Python'
>>> y1 = eval(str(y))
Traceback (most recent call last):
File "<pyshell#51>", line 1, in <module>
y1 = eval(str(y))
File "<string>", line 1, in <module>
NameError: name 'Python' is not defined

datetimeオブジェクトでの比較例

両者の違いをより明確に示すもう一つの例がこちらです。

>>> import datetime
>>> now = datetime.datetime.now()
>>> str(now)
'2019-03-29 01:29:23.211924'
>>> repr(now)
'datetime.datetime(2019, 3, 29, 1, 29, 23, 211924)'

上記の出力を見ると、str(now)はnowオブジェクトの値を含む人間が読みやすい文字列を返すのに対し、repr(now)はnowオブジェクトを再構築するために必要なPythonコードをそのまま返していることがわかります。

str()とrepr()の主な違いまとめ

str()repr()
オブジェクトを人間が読みやすい形にするオブジェクトを再現できるコードを返す
エンドユーザー向けの出力を生成開発者向けの出力を生成

実装時のポイント

自分でクラスを定義して__str__と__repr__を実装する際には、上記のポイントを考慮することが重要です。デバッグやログ出力にはrepr()形式が適しており、ユーザーへの画面表示にはstr()形式が適しています。両者を適切に使い分けることで、より保守しやすく読みやすいPythonコードを書けるようになります。

  1. 【初心者向け】Pythonのissuperset()メソッドの使い方をわかりやすく解説

    はじめにこの記事では、Pythonのissuperset()メソッドについて、基本的な仕組みから実際のコード例まで詳しく解説します。issuperset()は、セット(集合)に対して使用できるメソッドで、引数として渡されたセットのすべての要素が、呼び出し元のセットに含まれているかどうかを判定します。呼び出し元のセットBが、引数のセットAのすべての要素を含んでいる場合 → True を返すセットAの要素がすべてBに含まれていない場合 → False を返すつまり、「BがAの上位集合(スーパーセット)であるかどうか」を判定するためのメソッドです。基本構文B.issuperset(A)この式は、Bが

  2. Pythonで区切り文字(str)を指定して文字列を分割する方法

    Pythonで文字列を特定の区切り文字で分割する方法は、主に2つあります。1つは文字列クラスの組み込みメソッド split() を使う方法、もう1つは正規表現モジュール re の re.split() を使う方法です。それぞれの使い方を詳しく見ていきましょう。 split()メソッドで文字列を分割する PythonのStringクラスには split() というメソッドが用意されており、区切り文字をオプション引数として指定できます。引数を省略した場合、デフォルトの区切り文字は空白(ホワイトスペース)になります。 >>> aa-ab-ca.split(-) [aa, ab, c