私もそうでしたが、他言語からPythonにくると独特のクセに困惑することがあります。
最初に「これは何のためにあるのか」と不思議に思ったのがrepr()
です。str()
があるのに、どう使い分けたら良いのか理解できませんでした。こういうのは自分なりに概念を理解していないと活用できません。
以下の表に両者の違いをまとめてみました。同じような疑問を持つ他言語経験者の参考になれば嬉しいです。コードの検証にはPython3.6.4を用いました。
関数 | 戻り値 | 用途 |
---|---|---|
str(object) |
objectをユーザーが読みやすい文字列に変換して返す。 | エンドユーザーに出力する。 |
repr(object) |
objectをeval() で再び元のオブジェクトに戻せる文字列に変換して返す。representationの略。 |
デバッグ用に出力する。 |
str()
がJavaのクラスでオーバーライドするtoString()メソッド(C#のToString()メソッド)のイメージです。repr()
は引数付きのコンストラクタ(または初期化子)を文字列で返してくれる関数と解釈できます。
datetime
モジュールで確認すると分かりやすいです。
>>> import datetime
>>> today = datetime.date.today()
>>> str(today)
'2018-04-12'
>>> repr(today)
'datetime.date(2018, 4, 12)'
>>> today
datetime.date(2018, 4, 12)
>>> x = eval(repr(today))
>>> today - x
datetime.timedelta(0)
上記のコードでstr(today)
で出力される‘2018-04-12’だけでは、today
が文字列なのか、dateオブジェクトなのか見分けがつきません。
repr(today)
の方はtodayがdatetime.dateオブジェクトであることがわかるのでデバッグの時に役に立ちます。デバッグではprint()
をよく用いますが、オブジェクトの内容を確認したい場合にはrepr()
の結果を出力します。
つまり、print(today)
ではなく、print(repr(today))
とします。
対話モードでは変数を入力してEnterすれば、オブジェクトの内容を確認できますが、ファイル(*.py)ではそれができないので、代わりにrepr()
があると考えられます。
上記のコードでも、datetime.date(2018, 4, 12)
の部分は、対話モードで直接出力した内容と同じになるのを確認できます。
eval()とは
eval()
を使う機会は実際のところ少ないと思いますが、クラスのなかで自分で__repr__
メソッドをコーディングする場合はeval()
で元のオブジェクトに戻せるか確認することになります。
eval()
とは、引数の文字列をPythonの式として実行する関数です(evaluateの略です)。例えば、eval('3*5')
とすると15
を出力します。Pythonの式をそのまま実行するので、ユーザーが入力した式を受け入れてしまうとプログラムのセキュリティが低下します。その点は十分な注意が必要です。
ちなみにJavaScriptにも同様の機能をもつeval関数があり、同様にセキュリティの問題が指摘されてます。以下の本では、eval関数の問題点が明確に指摘されています。言語は違いますが、なかなか面白い本ですので、興味があればご一読ください。