3315

Pythonの__str__との違いは何ですか?__repr__

4

25 に答える 25

3187

アレックスはうまくまとめましたが、驚くべきことに簡潔すぎました。

まず、アレックスの投稿の要点を繰り返します。

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

デフォルトの実装は役に立たない

Python のデフォルトはかなり便利な傾向があるため、これはほとんど驚きです。ただし、この場合、次の__repr__ように動作するデフォルトを設定します。

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

あまりにも危険でした (たとえば、オブジェクトが相互に参照している場合、無限再帰に陥りやすいなど)。したがって、Python は対処します。true であるデフォルトが 1 つあることに注意してください。__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(l) + "]")

(おそらく、辞書をどうするかを理解することもできます。

概要

実装__repr__する任意のクラスに実装します。これは第二の性質であるべきです。__str__読みやすさの面でエラーになる文字列バージョンがあると便利だと思う場合は実装してください。

于 2010-04-13T00:56:52.533 に答える
689

私の経験則: __repr__開発者向けで__str__あり、顧客向けです。

于 2009-09-17T11:35:13.673 に答える
469

そうしないように具体的に行動しない限り、ほとんどのクラスは次のいずれにも役立つ結果をもたらしません。

>>> class Sic(object): pass
... 
>>> print(str(Sic()))
<__main__.Sic object at 0x8b7d0>
>>> print(repr(Sic()))
<__main__.Sic object at 0x8b7d0>
>>> 

ご覧のとおり、違いはなく、クラスとオブジェクトのid. 2つのうちの1つだけをオーバーライドする場合...:

>>> class Sic(object): 
...   def __repr__(self): return 'foo'
... 
>>> print(str(Sic()))
foo
>>> print(repr(Sic()))
foo
>>> class Sic(object):
...   def __str__(self): return 'foo'
... 
>>> print(str(Sic()))
foo
>>> print(repr(Sic()))
<__main__.Sic object at 0x2617f0>
>>> 

ご覧のとおり、 をオーバーライドすると、それは__repr__にも使用されますが、__str__その逆はありません。

知っておくべきその他の重要な情報:__str__組み込みのコンテナーでは、含まれる__repr__アイテム__str__に ではなく を使用します。__repr__そして、典型的なドキュメントに見られる主題に関する言葉にもかかわらず、 オブジェクトの を、等しいオブジェクトを構築するために使用できる文字列にすることを気にする人はほとんどevalいません (それは難しすぎます。また、関連するモジュールが実際にどのようにインポートされたかがわからないため、完全に不可能)。

__str__したがって、私__repr__のアドバイス:__repr__の戻り値を__eval__!

于 2009-09-17T04:49:40.083 に答える
195

__repr__: Python オブジェクトの表現は通常、eval によってそのオブジェクトに変換されます。

__str__: は、テキスト形式のオブジェクトであると思われるものです

例えば

>>> s="""w'o"w"""
>>> repr(s)
'\'w\\\'o"w\''
>>> str(s)
'w\'o"w'
>>> eval(str(s))==s
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    w'o"w
       ^
SyntaxError: EOL while scanning single-quoted string
>>> eval(repr(s))==s
True
于 2009-09-17T04:35:36.693 に答える
188

要するに、 の目標は、__repr__あいまいさをなくし、__str__読みやすくすることです。

良い例を次に示します。

>>> import datetime
>>> today = datetime.datetime.now()
>>> str(today)
'2012-03-14 09:21:58.130922'
>>> repr(today)
'datetime.datetime(2012, 3, 14, 9, 21, 58, 130922)'

repr については、次のドキュメントを参照してください。

repr(object)

オブジェクトの印刷可能な表現を含む文字列を返します。これは、変換 (逆引用符) によって得られる値と同じです。この操作に通常の関数としてアクセスできると便利な場合があります。多くの型について、この関数は、 に渡されたときに同じ値を持つオブジェクトを生成する文字列を返そうとしますeval()。それ以外の場合、オブジェクトの型の名前と追加情報を含む山かっこで囲まれた文字列が表現されます。多くの場合、オブジェクトの名前とアドレスが含まれます。クラスは、メソッドを定義することにより、この関数がそのインスタンスに対して返すものを制御できます__repr__()

str のドキュメントは次のとおりです。

str(object='')

オブジェクトのきれいに印刷可能な表現を含む文字列を返します。文字列の場合、これは文字列自体を返します。との違いrepr(object)str(object)、 が受け入れられる文字列を常に返そうとするとは限らないことeval()です。その目標は、印刷可能な文字列を返すことです。引数が指定されていない場合は、空の文字列 を返します''

于 2013-10-25T18:38:52.457 に答える
145

Pythonの__str__との違いは何ですか?__repr__

__str__(「dunder (ダブルアンダースコア) 文字列」と__repr__読む) と (「dunder-repper」 (「表現」の意味) と読む) はどちらも、オブジェクトの状態に基づいて文字列を返す特別なメソッドです。

__repr____str__が欠落している場合のバックアップ動作を提供します。

そのため、最初に a__repr__を記述して、返される文字列から同等のオブジェクトを再インスタンス化できるようにする必要がありますeval

後でいつでも__str__、ユーザーが読み取り可能なインスタンスの文字列表現を書くことができます。

__str__

オブジェクトを出力するか、 、 、または に渡すformat場合str.formatstrメソッド__str__が定義されている場合はそのメソッドが呼び出され、定義されていない場合はそのメソッドが__repr__使用されます。

__repr__

__repr__メソッドは組み込み関数によって呼び出され、reprオブジェクトを返す式を評価するときに Python シェルにエコーされます。

のバックアップを提供するので、__str__1つしか書き込めない場合は、最初から__repr__

の組み込みヘルプは次のreprとおりです。

repr(...)
    repr(object) -> string

    Return the canonical string representation of the object.
    For most object types, eval(repr(object)) == object.

つまり、ほとんどのオブジェクトでは、 によって出力されるものを入力reprすると、同等のオブジェクトを作成できるはずです。しかし、これはデフォルトの実装ではありません。

のデフォルト実装__repr__

デフォルトのオブジェクト__repr__は ( C Python source ) のようなものです:

def __repr__(self):
    return '<{0}.{1} object at {2}>'.format(
      self.__module__, type(self).__name__, hex(id(self)))

つまり、デフォルトでは、オブジェクトの元のモジュール、クラス名、およびメモリ内の場所の 16 進数表現を出力します。たとえば、次のようになります。

<__main__.Foo object at 0x7f80665abdd0>

この情報はあまり役に立ちませんが、特定のインスタンスの正規表現を正確に作成する方法を導き出す方法はありません。少なくとも、メモリ内で一意に識別する方法を教えてくれるので、何もないよりはましです。

どの__repr__ように役立ちますか?

datetimePython シェルとオブジェクトを使用して、それがどれほど役立つかを見てみましょう。まず、datetimeモジュールをインポートする必要があります:

import datetime

シェルで呼び出すdatetime.nowと、同等の datetime オブジェクトを再作成するために必要なものがすべて表示されます。これは datetime によって作成されます__repr__:

>>> datetime.datetime.now()
datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)

datetime オブジェクトを出力すると、人間が判読できる (実際には ISO) 形式が表示されます。これは、datetime によって実装され__str__ます。

>>> print(datetime.datetime.now())
2015-01-24 20:05:44.977951

失ったオブジェクトを再作成するのは簡単なことです。これは、出力からコピーして貼り付けてから印刷することによって変数に代入しなかったためです__repr__。他のオブジェクトと同じ人間が読める出力でそれを取得します。

>>> the_past = datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)
>>> print(the_past)
2015-01-24 20:05:36.491180

どうすれば実装できますか?

開発中は、可能であればオブジェクトを同じ状態で再現できるようにしたいと思うでしょう。たとえば、これは datetime オブジェクトの定義方法です__repr__( Python source )。このようなオブジェクトを再現するために必要なすべての属性があるため、かなり複雑です。

def __repr__(self):
    """Convert to formal string, for repr()."""
    L = [self._year, self._month, self._day,  # These are never zero
         self._hour, self._minute, self._second, self._microsecond]
    if L[-1] == 0:
        del L[-1]
    if L[-1] == 0:
        del L[-1]
    s = "%s.%s(%s)" % (self.__class__.__module__,
                       self.__class__.__qualname__,
                       ", ".join(map(str, L)))
    if self._tzinfo is not None:
        assert s[-1:] == ")"
        s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
    if self._fold:
        assert s[-1:] == ")"
        s = s[:-1] + ", fold=1)"
    return s

オブジェクトをより人間が読める表現にしたい場合は、次に実装できます__str__。datetime オブジェクト ( Python ソース) が を実装する方法は次の__str__とおりです。これは、ISO 形式で表示する関数が既にあるため、簡単に実行できます。

def __str__(self):
    "Convert to string, for str()."
    return self.isoformat(sep=' ')

セット__repr__ = __str__

これは、設定を提案する別の回答に対する批判です__repr__ = __str__

設定__repr__ = __str__はばかげています -__repr__は と のフォールバックで__str__あり、__repr__開発者がデバッグで使用するために書かれており、__str__.

__str__オブジェクトのテキスト表現が必要な場合にのみ が必要です。

結論

作成するオブジェクトを定義__repr__して、開発時にそれを使用するときに、あなたや他の開発者が再現可能な例を持てるようにします。__str__人間が読める文字列表現が必要な場合を定義します。

于 2015-01-25T02:01:30.503 に答える
46

ハンス・ペッター・ラングタンゲンによる計算科学のための Python スクリプトの本の 358 ページには、次のように明確に述べられています。

  • は、オブジェクトの__repr__完全な文字列表現を目指しています。
  • __str__、印刷用の適切な文字列を返すことです。

だから、私はそれらを次のように理解することを好みます

  • repr = 再現する
  • str = 文字列 (表現)

これは、Python を学習するときに私が犯した誤解ですが、ユーザーの観点からです。

小さくても良い例も同じページに次のように示されています。

In [38]: str('s')
Out[38]: 's'

In [39]: repr('s')
Out[39]: "'s'"

In [40]: eval(str('s'))
Traceback (most recent call last):

  File "<ipython-input-40-abd46c0c43e7>", line 1, in <module>
    eval(str('s'))

  File "<string>", line 1, in <module>

NameError: name 's' is not defined


In [41]: eval(repr('s'))
Out[41]: 's'
于 2017-05-21T16:34:21.163 に答える
44

与えられたすべての回答とは別に、いくつかの点を追加したいと思います:-

1)__repr__()は、インタラクティブな python コンソールにオブジェクトの名前を入力して Enter キーを押すだけで呼び出されます。

2)__str__()オブジェクトを print ステートメントで使用すると呼び出されます。

3) が欠落している場合は、オブジェクトの呼び出しを__str__使用して印刷および関数を実行します。str()__repr__()

4)__str__()コンテナーの場合、呼び出されると__repr__()、含まれている要素のメソッドが実行されます。

5)str()内部で呼び出されると__str__()、基本ケースなしで再帰する可能性があり、再帰の最大深度でエラーが発生する可能性があります。

6)自動的に無限再帰を回避しようとする which を__repr__()呼び出すことができrepr()、既に表現されているオブジェクトを に置き換えます...

于 2016-09-08T03:27:45.767 に答える
13

正直なところ、eval(repr(obj))使用されることはありません。evalそれを使用していることに気付いた場合は、危険であり、文字列はオブジェクトをシリアル化する非常に非効率的な方法であるため、停止する必要があります(pickle代わりに使用してください)。

したがって、を設定することをお勧めします__repr__ = __str__。その理由は、要素をstr(list)要求reprすることです(これは、Python 3では対処されなかったPythonの最大の設計上の欠陥の1つであると私は考えています)。実際のreprは、の出力としてはおそらくあまり役​​に立ちませんprint([your, objects])

これを修飾するために、私の経験では、関数の最も有用なユースケースはrepr、文字列を別の文字列内に配置することです(文字列フォーマットを使用)。このように、引用符などをエスケープすることを心配する必要はありません。ただし、evalここでは何も起こらないことに注意してください。

于 2012-11-15T10:39:22.003 に答える
13

effbotによる(非公式の)PythonリファレンスWiki(アーカイブコピー)から:

__str__"オブジェクトの「非形式的な」文字列表現を計算します。これは、有効な Python 式である必要がないという点で とは異なります。__repr__代わりに、より便利で簡潔な表現を使用できます。 "

于 2009-09-17T04:28:52.177 に答える
11

str- 指定されたオブジェクトから新しい文字列オブジェクトを作成します。

repr- オブジェクトの正規の文字列表現を返します。

違い:

str():

  • オブジェクトを読み取り可能にする
  • エンドユーザー向けの出力を生成します

repr():

  • オブジェクトを再現するコードが必要
  • 開発者向けの出力を生成します
于 2016-12-04T16:18:48.080 に答える
5

__str__優れた回答は、との違いをすでにカバーしてい__repr__ます。私にとっては、前者はエンド ユーザーでも読みやすく、後者は開発者にとって可能な限り有用であるということです。それを考えると、開発者にとって有用な情報が省略され__repr__ているため、デフォルトの実装ではこの目標を達成できないことがよくあります。

このため、私が十分に単純な を持っている場合__str__、私は通常、次のようなもので両方の世界を最大限に活用しようとします:

def __repr__(self):
    return '{0} ({1})'.format(object.__repr__(self), str(self))
于 2015-10-29T17:46:48.673 に答える
4
>>> print(decimal.Decimal(23) / decimal.Decimal("1.05"))
21.90476190476190476190476190
>>> decimal.Decimal(23) / decimal.Decimal("1.05")
Decimal('21.90476190476190476190476190')

生の数値の結果に対してがprint()呼び出されると、出力されます。decimal.Decimal(23) / decimal.Decimal("1.05")この出力は、で実現できる文字列形式__str__()です。単純に式を入力すると、decimal.Decimal出力が得られます — この出力は、で実現できる表現形式__repr__()です。すべての Python オブジェクトには 2 つの出力形式があります。文字列形式は、人間が判読できるように設計されています。表現形式は、Python インタープリターに供給された場合に (可能な場合) 表現されたオブジェクトを再現する出力を生成するように設計されています。

于 2015-07-15T10:30:35.593 に答える
2

__repr__printandメソッド以外のあらゆる場所で使用されstrます ( a__str__が定義されている場合!)

于 2018-05-08T08:49:10.853 に答える