ベストアンサー1
アレックス・マルテッリはよくまとめたしかし、驚いたことに、それはあまりにも簡潔すぎました。
まず、主なポイントをもう一度述べます。アレックスの投稿:
- デフォルトの実装は役に立たない(役に立たないものを考えるのは難しいですが、そうですね)
__repr__
目標は明確であること__str__
目標は読みやすいこと- コンテナは
__str__
含まれるオブジェクトを使用する__repr__
デフォルトの実装は役に立たない
Python のデフォルトはかなり便利な傾向があるため、これはほとんど驚きです。ただし、この場合、デフォルトがあると、__repr__
次のように動作します。
return "%s(%r)" % (self.__class__, self.__dict__)
はあまりにも危険です (たとえば、オブジェクトがお互いを参照する場合、無限再帰に陥りやすい)。そのため、Python は回避します。1 つのデフォルトが true であることに注意してください。 が__repr__
定義されていて、__str__
が定義されていない場合、オブジェクトは であるかのように動作します__str__=__repr__
。
つまり、簡単に言えば、実装するほぼすべてのオブジェクトには、__repr__
オブジェクトを理解するために使用できる関数が必要です。実装は__str__
オプションです。「きれいな印刷」機能 (たとえば、レポート ジェネレーターで使用される機能) が必要な場合に実装します。
の目標は__repr__
明確であることである
はっきり言っておきます。私はデバッガーを信じていません。デバッガーの使い方をまったく知りませんし、真剣に使ったこともありません。さらに、デバッガーの大きな欠点はその基本的な性質にあると考えています。私がデバッグするほとんどの障害は、はるか昔、はるか遠くの銀河で起こったものです。つまり、私はロギングを宗教的な熱意で信じているのです。ロギングは、まともなファイアアンドフォーゲットサーバーシステムの生命線です。Python ではロギングが簡単です。プロジェクト固有のラッパーがあれば、必要なのは
log(INFO, "I am in the weird function and a is", a, "and b is", b, "but I got a null C — using default", default_c)
しかし、最後のステップを実行する必要があります。実装するすべてのオブジェクトに有用な repr があり、そのようなコードが問題なく機能することを確認してください。これが「eval」が出てくる理由です。 について十分な情報がある場合eval(repr(c))==c
、 について知っておくべきことがすべてわかっていることを意味しますc
。それが簡単であれば、少なくともあいまいな方法でそうしてください。そうでない場合は、c
とにかく について十分な情報があることを確認してください。私は通常、eval のような形式を使用します。"MyClass(this=%r,that=%r)" % (self.this,self.that)
これは、実際に MyClass を構築できることや、それらが正しいコンストラクター引数であることを意味するわけではありませんが、「これがこのインスタンスについて知っておく必要があるすべてです」と表現するのに便利な形式です。
注:%r
上記では を使用し、 は使用していません%s
。実装内では常にrepr()
[ または%r
同等の書式設定文字 ]を使用する必要があります。そうしないと、repr の目的が達成されません。と を__repr__
区別できるようにする必要があります。MyClass(3)
MyClass("3")
の目標は__str__
読みやすいことです
具体的には、これは曖昧さをなくすためのものではありません。注意してくださいstr(3)==str("3")
。同様に、IP 抽象化を実装する場合、その str が 192.168.1.1 のようであっても問題ありません。日付/時刻抽象化を実装する場合、str は「2010/4/12 15:35:22」などになります。目標は、プログラマではなくユーザーが読みたいと思うような方法で表現することです。無駄な数字を切り落とし、他のクラスのふりをします。読みやすさがサポートされている限り、それは改善です。
コンテナは__str__
含まれるオブジェクトを使用する__repr__
これは意外なことではないでしょうか。少しですが、 を使用した場合、どの程度読みやすくなるでしょうか__str__
。
[moshe is, 3, hello
world, this is a list, oh I don't know, containing just 4 elements]
あまりそうではありません。具体的には、コンテナ内の文字列は、その文字列表現を乱すのが非常に簡単だとわかります。曖昧さに直面しても、Pythonは推測する誘惑に抵抗することを覚えておいてください。リストを印刷するときに上記の動作が必要な場合は、
print("[" + ", ".join(lst) + "]")
(辞書についても、おそらく何をすべきかがわかるでしょう)。
まとめ
実装するすべてのクラスに実装します__repr__
。これは当然のことです。__str__
読みやすさを重視した文字列バージョンがあると便利だと思う場合は実装します。