簡単にいってしまうと、これら2つの関数には次のような目的の違いがある。
ここでいう「非公式」な文字列表現とは、「人が読める簡潔な表現」を意味している。対して、「公式な文字列表現」とは、「Pythonにとって意味のある表現」を意味している。
ここでいう「Pythonにとって意味のある表現」とは次のような意味合いだ。
このうちの前者が文字列'Hello'をstr関数とrepr関数で文字列化したときの差につながっている。2つの関数の戻り値がどうなっているのかを、より明確にするために少し試してみよう。
まず以下のコードを実行する。
str('Hello')
この実行結果は次のようになる。
次に、以下のコードを実行する。
repr('Hello')
こちらの実行結果は次のようになる。
お分かりだろうか。こちらはシングルクオートで囲まれた「'Hello'」がさらにダブルクオート「"」で囲まれて「"'Hello'"」となっている。
ここでPythonには組み込みのeval関数がある。これは引数に受け取った文字列の値を「Pythonの式」として評価して、その結果を戻り値とするものだ。
eval(expression)
expressionの値を「Pythonの式」として評価して、その結果を戻り値とする。expressionの評価時には、その評価で使用する名前空間として辞書を渡せるが、ここでは省略する。
パラメーター | 説明 |
---|---|
expression | Pythonの式として評価する文字列 |
eval関数のパラメーター |
この関数を使って、「オブジェクトを復元」してみよう。まずは「オブジェクトを復元する」ことを目的としたrepr関数を使ってみよう。
hello = repr('Hello')
print(len(hello))
eval(hello)
実行結果は次のようになる。
ご覧のように文字数が「7」であることが示された後で、最後に「'Hello'」と表示され、文字列'Hello'が復元されたことが分かる。では、次にstr関数を使って同じことをしてみよう。
hello = str('Hello')
print(len(hello))
eval(hello)
実行結果は次のようになる。
上の画像に示した通り、これはエラー(NameError例外)となる。と同時に、文字列の長さが「5」であることにも注目しよう。
なぜこのような違いが出たかを考えてみよう。まず、repr関数が返した値は「"'Hello'"」となっていた。外側のダブルクオートは「'Hello'」を囲んでいる。つまり、文字列の値そのものは「'Hello'」である。これをeval関数に渡すと、「'Hello'」という文字列として評価される。そのため、これはエラーとはならない。
これに対して、str関数が返した値は「'Hello'」であり、その値は「Hello」という「5」文字の文字列である。つまり、eval関数にはシングルクオートで囲まれていない「Hello」が渡されることになる。これをPythonが評価しようとして、「Hello」という「名前」はないよ、というエラーになったということだ。
これがstr関数とrepr関数の差といえる。前者は人が読みやすい表現(「Hello」だけ)となり、後者はPythonにとって意味のある表現(復元可能な文字列表現)となっている(ただし、クオート文字が二重になり、人が見ると冗長に感じられるかもしれない)。ただし、今見たのは文字列を例に取ったものであり、他のオブジェクトでは同じものが得られることもあれば、両者の結果がもっと大きく異なることもある。
例えば、先ほどリストや整数をstr関数やrepr関数に渡したときに、その結果が同じになった。これは、シングルクオートで囲んだ「'[1, 2, 3]'」などはeval関数に渡しても、リストとしてきちんと評価できることからと考えられる。と、同時に「'[1, 2, 3]'」というのは人の目にも分かりやすい表現となっている。
このように、repr関数はまず元のオブジェクトを復元できることを目的とした文字列表現を作成することを念頭に置いている。ただし、そうでない場合には、プログラムをデバッグするときなどに有用な情報を山かっこ「<>」に囲んだものを返すべきとしている。
例えば、関数を定義して、その公式な文字列表現を得てみよう。
def somefunc():
print('some func')
repr(somefunc)
この場合の実行結果は次のようになる。
山かっこ「<>」に囲まれて、その型(function)と関数名(somefunc)、最後にそのアイデンティティーが表示された。これが、オブジェクトを復元できないが、役に立つ情報の例だ。興味のある人は、いろいろなオブジェクトをstr関数やrepr関数で文字列化してみよう。
なお、str関数にオブジェクトを渡して、その非公式な文字列表現を得ようとしたときに、それが用意されていないと、最終的にはその公式な文字列表現が返される。そのため、非公式な文字列表現と公式な文字列表現が同じ(同じで十分)なこともある。この仕組みについては、後続の回で取り上げる予定だ。
今回はオブジェクトのアイデンティティーと、その比較、文字列表現について見た。次回は、これまでに出てきた演算子を含めて、Pythonの演算子についてざっくりとまとめる。
「Python入門」
Copyright© Digital Advantage Corp. All Rights Reserved.