1. ホーム
  2. パイソン

[解決済み】__str__と__repr__の違いは何ですか?

2022-03-17 11:22:18

質問

とはどのような違いがあるのでしょうか? __str____repr__ をPythonで使うのですか?

どのように解決するのですか?

アレックス はよくまとまっているが、意外と簡潔すぎた。

まず、以下の要点を再確認しておきます。 アレックスの投稿 :

  • デフォルトの実装は役に立たない(そうでないものを考えるのは難しいが、そうだ)。
  • __repr__ 目標は曖昧さをなくすこと
  • __str__ 目標は読みやすいこと
  • コンテナの __str__ は、含まれるオブジェクトの __repr__

デフォルトの実装では意味がない

Pythonのデフォルトはかなり有用であることが多いので、これはほとんど驚きです。しかし、このケースでは __repr__ のように振る舞うことになる。

return "%s(%r)" % (self.__class__, self.__dict__)

は危険すぎる(たとえば、オブジェクトが互いに参照し合うと、無限再帰に陥りやすい)。そのため、Pythonは手を抜いています。1つのデフォルトが真であることに注意してください。 __repr__ が定義されており __str__ がない場合、オブジェクトはあたかも __str__=__repr__ .

これは、簡単に言うと、実装するほとんどすべてのオブジェクトに、機能的な __repr__ そのオブジェクトを理解するために使えるものです。実装する __str__ はオプションです。"pretty print" 機能が必要な場合 (例えば、レポートジェネレータで使用する場合) は、そうしてください。

の目的は __repr__ は、曖昧でないこと

はっきり言いますが、私はデバッガーを信じていません。デバッガの使い方をよく知らないし、真剣に使ったこともない。さらに、デバッガの大きな欠点は、その基本的な性質にあると思います。私がデバッグしたほとんどの失敗は、はるか彼方の銀河系で、ずっと昔に起こったことなのです。つまり、私はロギングを宗教的な熱意を持って信じているのです。ロギングは、まともなfire-and-forgetサーバーシステムの活力源です。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(l) + "]")

(辞書をどうするかというのも、おそらくわかると思います。

概要

実装 __repr__ は、どのようなクラスでも実装することができます。これは自然に身につくはずです。実装 __str__ もし、読みやすさを優先して文字列のバージョンを用意したほうがいいと思うのなら。