web-dev-qa-db-ja.com

__str__と__repr__の違いは?

Pythonにおける__str____repr__の違いは何ですか?

2377
Casebash

Alex はよくまとめたが、驚くべきことに、あまりにも簡潔だった。

まず、 Alexの投稿 にある要点をもう一度述べさせてください。

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

デフォルトの実装は役に立ちません

Pythonのデフォルトはかなり役に立つ傾向があるので、これはほとんど驚きです。しかし、この場合、__repr__のデフォルト値は次のようになります。

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

危険が大きすぎたでしょう(たとえば、オブジェクトが互いに参照し合う場合、無限の再帰にたどり着くのは簡単すぎます)。それでPythonは対処します。 __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を使用しました。 %rの実装の中では、常にrepr() [または__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__を使用します

これは驚くべきことではないでしょうか。それは少しですが、どれほど読みやすいでしょう

[moshe is, 3, hello
world, this is a list, oh I don't know, containing just 4 elements]

ありますか?そうではありません。具体的には、コンテナ内の文字列は、その文字列表現を乱すことが非常に簡単な方法です。あいまいさに直面して、覚えておいて、Pythonは推測する誘惑に抵抗します。リストを印刷するときに上記の動作が必要な場合は、

print "[" + ", ".join(l) + "]"

(あなたはおそらく辞書について何をすべきかを考え出すことができます。

要約

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

2435
moshez

私の経験則:__repr__は開発者向け、__str__はお客様向けです。

442
Ned Batchelder

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

>>> 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__(object): return 'foo'
... 
>>> print str(Sic())
foo
>>> print repr(Sic())
foo
>>> class Sic(object):
...   def __str__(object): 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__への入力として!

371
Alex Martelli

つまり、__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()に受け入れられる文字列を返そうとしないことです。その目的は印刷可能な文字列を返すことです。引数が指定されていない場合は、空の文字列''を返します。

130
bitoffdev

Pythonの__str____repr__の違いは何ですか?

__str__( "dunder(double-underscore)string"として読む)と__repr__( "Representation"のために "dunder-repper"として読む)はどちらもオブジェクトの状態に基づいて文字列を返す特別なメソッドです。

__repr__が存在しない場合、__str__はバックアップ動作を提供します。

それで、最初にそれが返す文字列から同等のオブジェクトを再インスタンス化することを可能にする__repr__を書くべきです。 evalを使用するか、Pythonシェルで文字ごとに入力します。

それが必要であると考えるとき、いつでも、インスタンスのユーザが読める文字列表現のために__str__を書くことができます。

__str__

オブジェクトを印刷するか、formatstr.format、またはstrに渡すと、__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__はどのように役立つのでしょうか。

Pythonシェルとdatetimeオブジェクトを使って、どれだけ便利に使えるかを見てみましょう。まずdatetimeモジュールをインポートする必要があります。

import datetime

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

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

Datetimeオブジェクトを印刷すると、人間が判読できる(実際にはISO)形式のNiceが表示されます。これは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 = ", ".join(map(str, L))
    s = "%s(%s)" % ('datetime.' + self.__class__.__name__, s)
    if self._tzinfo is not None:
        assert s[-1:] == ")"
        s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
    return s

あなたのオブジェクトにもっと人間的に読みやすい表現を持たせたいなら、次に__str__を実装することができます。これはdatetimeオブジェクト( Python source )が__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__を定義します。

95
Aaron Hall

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

1)対話型のpythonコンソールに単にオブジェクトの名前を書いてenterを押すと__repr__()が呼び出されます。

2)print文でobjectを使うと、__str__()が呼び出されます。

3)__str__が欠落している場合、printとstr()を使用するすべての関数がobjectの__repr__()を呼び出します。

4)コンテナの__str__()は、呼び出されると、それに含まれる要素の__repr__()メソッドを実行します。

5)str()内で呼び出された__str__()は基本ケースなしで再帰的に再帰する可能性があり、最大再帰深さでエラーになります。

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

本の358ページの 計算科学のためのPythonスクリプト / Hans Petter Langtangenによると、それははっきりと述べている

  • __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'
17
Yong Yang

正直なところ、eval(repr(obj))は決して使われていません。 evalは危険であり、文字列はオブジェクトを直列化するための非常に非効率的な方法であるため、やめてください(代わりにpickleを使用してください)。

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

これを限定するために、私の経験では、repr関数の最も有用な使用例は、(文字列フォーマットを使用して)別の文字列の中に文字列を入れることです。このように、あなたは引用符や何かをエスケープすることを心配する必要はありません。しかし、ここではevalは発生していません。

11
asmeurer

簡単に言えば:

__str__はあなたのオブジェクトの文字列表現を示すのに使われます 簡単に読めるように 他の人たちによって - .

__repr__オブジェクトの文字列表現を示すために使用されます。

分数の文字列表現が '(1/2)'で、オブジェクト(Fractionクラス)が 'Fraction(1,2)'として表現されるFractionクラスを作成したいとしましょう。

簡単なFractionクラスを作成することができます。

class Fraction:
    def __init__(self, num, den):
        self.__num = num
        self.__den = den

    def __str__(self):
        return '(' + str(self.__num) + '/' + str(self.__den) + ')'

    def __repr__(self):
        return 'Fraction (' + str(self.__num) + ',' + str(self.__den) + ')'



f = Fraction(1,2)
print('I want to represent the Fraction STRING as ' + str(f)) # (1/2)
print('I want to represent the Fraction OBJECT as ', repr(f)) # Fraction (1,2)
11
Zer0

http://pyref.infogami.com/__str__ からeffbot:

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

10
Casebash

他の答えで欠けている一面。一般的なパターンは次のとおりです。

  • __str__の目的:人間が読めるもの
  • __repr__の目的:evalを介した明確な、おそらく機械可読な

残念なことに、Python REPLとIPythonはREPLコンソールでオブジェクトを印刷するために__repr__を使うので、この区別に欠陥があります( PythonIPython)の関連質問を参照 )そのため、対話型コンソール作業(NumpyやPandasなど)を対象としたプロジェクトは、上記の規則を無視し、代わりに人間が読める__repr__の実装を提供するようになりました。

7
bluenote10

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

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

違い:

str():

  • オブジェクトを読みやすくする
  • エンドユーザー用の出力を生成します

repr():

  • オブジェクトを再現するコードが必要
  • 開発者向けの出力を生成します
6
Inconnu

blog からより明確に

str はtoStringに似ています。あなたがデータを印刷することができるように作成されます repr はシリアル化、またはピクルスのようです。どのように私は_ recreate私はeval()を使用してそうする必要があるならこのオブジェクト

>>> import datetime
>>> now = datetime.datetime.now() 
>>> str(now)
'2015-04-04 20:51:31.766862'
>>> repr(now)
'datetime.datetime(2015, 4, 4, 20, 51, 31, 766862)'
>>mydate = eval(repr(now))
5

__str____repr__の違いはすでに優れた答えでカバーされています。これは、前者がエンドユーザーでも読み取り可能であること、そして後者が開発者にとってできるだけ有用であることを意味します。それを考えれば、__repr__のデフォルトの実装では、この目的を達成できないことがよくあります。なぜなら、という情報を開発者にとって有用ではないからです。

このため、__str__という単純なものがあれば、私は一般的に以下のような方法で両方の長所を最大限に活用しようとします。

def __repr__(self):
    return '{0} ({1})'.format(object.__repr__(self), str(self))
4
orome
"A basic requirement for a Python object is to provide usable 
 string   representations of itself, one used for debugging and
 logging, another for presentation to end users. That is why the  
 special methods __repr__ and __str__ exist in the data model."

本から:Fluent Python

4
Ijaz Ahmad Khan
>>> 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出力になります。この出力は 表現形式 /になります。すべてのPythonオブジェクトには2つの出力形式があります。文字列形式は人間が読めるように設計されています。表現形式は、Pythonインタプリタに渡されると(可能な場合)表現されたオブジェクトを再生成するような出力を生成するように設計されています。

3
BattleDrum

覚えておくべき1つの重要なことはコンテナの__str__が含まれているオブジェクトの__repr__を使うということです。

>>> from datetime import datetime
>>> from decimal import Decimal
>>> print (Decimal('52'), datetime.now())
(Decimal('52'), datetime.datetime(2015, 11, 16, 10, 51, 26, 185000))
>>> str((Decimal('52'), datetime.now()))
"(Decimal('52'), datetime.datetime(2015, 11, 16, 10, 52, 22, 176000))"

Pythonは読みやすさよりも曖昧さを排除します Tuple__str__呼び出しは含まれているオブジェクトの__repr__ "正式な" オブジェクトの表現を呼び出します。形式的表現は非公式の表現より読むのが難しいですが、それは明白でバグに対してより堅牢です。

3
zangw

手短に:

class Demo:
  def __repr__(self):
    return 'repr'
  def __str__(self):
    return 'str'

demo = Demo()
print(demo) # use __str__, output 'str' to stdout

s = str(demo) # __str__ is used, return 'str'
r = repr(demo) # __repr__ is used, return 'repr'

import logging
logger = logging.getLogger(logging.INFO)
logger.info(demo) # use __str__, output 'str' to stdout

from pprint import pprint, pformat
pprint(demo) # use __repr__, output 'repr' to stdout
result = pformat(demo) # use __repr__, result is string which value is 'str'
3
ShadowWalker

__str____repr__を直感的にそして永久に区別して理解する。

__str__は、目を読めるように、与えられたオブジェクトの偽装された本体を文字列で返します
__repr__は、明確に識別できるように、与えられたオブジェクトの実際の肉体を返します(自分自身を返します)。

例で見てください

In [30]: str(datetime.datetime.now())
Out[30]: '2017-12-07 15:41:14.002752'
Disguised in string form

__repr__に関して

In [32]: datetime.datetime.now()
Out[32]: datetime.datetime(2017, 12, 7, 15, 43, 27, 297769)
Presence in real body which allows to be manipulated directly.

__repr__の結果に対して算術演算を行えば便利です。

In [33]: datetime.datetime.now()
Out[33]: datetime.datetime(2017, 12, 7, 15, 47, 9, 741521)
In [34]: datetime.datetime(2017, 12, 7, 15, 47, 9, 741521) - datetime.datetime(2
    ...: 017, 12, 7, 15, 43, 27, 297769)
Out[34]: datetime.timedelta(0, 222, 443752)

__str__に操作を適用する場合

In [35]: '2017-12-07 15:43:14.002752' - '2017-12-07 15:41:14.002752'
TypeError: unsupported operand type(s) for -: 'str' and 'str'

エラー以外は何も返しません。

もう一つの例。

In [36]: str('string_body')
Out[36]: 'string_body' # in string form

In [37]: repr('real_body')
Out[37]: "'real_body'" #its real body hide inside

これがあなたがより多くの答えを探求するための具体的な根拠を築くのに役立つことを願っています。

2
JawSaw

__repr__printメソッドとstrメソッド以外ではどこでも使用されます(__str__が定義されている場合)。

1
trthhrtz
  1. __str__は文字列オブジェクトを返さなければなりませんが、__repr__は任意のpython式を返すことができます。
  2. __str__の実装が欠けている場合は、__repr__関数がフォールバックとして使用されます。 __repr__関数の実装が欠けていてもフォールバックはありません。
  3. __repr__関数がオブジェクトの文字列表現を返している場合は、__str__関数の実装をスキップできます。

ソース: https://www.journaldev.com/22460/python-str-repr-functions

0
Sampath

__str__は、str(obj)を呼び出すことでオブジェクトで呼び出すことができ、人間が読める文字列を返す必要があります。

__repr__は、repr(obj)を呼び出すことでオブジェクトで呼び出すことができ、内部オブジェクト(オブジェクトフィールド/属性)を返す必要があります

この例が役立つ場合があります。

class C1:pass

class C2:        
    def __str__(self):
        return str(f"{self.__class__.__name__} class str ")

class C3:        
    def __repr__(self):        
         return str(f"{self.__class__.__name__} class repr")

class C4:        
    def __str__(self):
        return str(f"{self.__class__.__name__} class str ")
    def __repr__(self):        
         return str(f"{self.__class__.__name__} class repr")


ci1 = C1()    
ci2 = C2()  
ci3 = C3()  
ci4 = C4()

print(ci1)       #<__main__.C1 object at 0x0000024C44A80C18>
print(str(ci1))  #<__main__.C1 object at 0x0000024C44A80C18>
print(repr(ci1)) #<__main__.C1 object at 0x0000024C44A80C18>
print(ci2)       #C2 class str
print(str(ci2))  #C2 class str
print(repr(ci2)) #<__main__.C2 object at 0x0000024C44AE12E8>
print(ci3)       #C3 class repr
print(str(ci3))  #C3 class repr
print(repr(ci3)) #C3 class repr
print(ci4)       #C4 class str 
print(str(ci4))  #C4 class str 
print(repr(ci4)) #C4 class repr
0
prosti