Python
における__str__
と__repr__
の違いは何ですか?
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__
を実装してください。
私の経験則:__repr__
は開発者向け、__str__
はお客様向けです。
特にそうするように明確に行動しない限り、ほとんどのクラスは次のいずれかに役立つ結果をもたらしません。
>>> 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__
への入力として!
つまり、
__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()
に受け入れられる文字列を返そうとしないことです。その目的は印刷可能な文字列を返すことです。引数が指定されていない場合は、空の文字列''
を返します。
Pythonの
__str__
と__repr__
の違いは何ですか?
__str__
( "dunder(double-underscore)string"として読む)と__repr__
( "Representation"のために "dunder-repper"として読む)はどちらもオブジェクトの状態に基づいて文字列を返す特別なメソッドです。
__repr__
が存在しない場合、__str__
はバックアップ動作を提供します。
それで、最初にそれが返す文字列から同等のオブジェクトを再インスタンス化することを可能にする__repr__
を書くべきです。 eval
を使用するか、Pythonシェルで文字ごとに入力します。
それが必要であると考えるとき、いつでも、インスタンスのユーザが読める文字列表現のために__str__
を書くことができます。
__str__
オブジェクトを印刷するか、format
、str.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__
を定義します。
与えられたすべての答えとは別に、私はいくつかの点を追加したいと思います -
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__
は、印刷に適した文字列を返すことです。だから、私はそれらを次のように理解することを好む
これは誤解ですがユーザーの観点から私は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'
正直なところ、eval(repr(obj))
は決して使われていません。 eval
は危険であり、文字列はオブジェクトを直列化するための非常に非効率的な方法であるため、やめてください(代わりにpickle
を使用してください)。
したがって、__repr__ = __str__
を設定することをお勧めします。その理由は、str(list)
が要素に対してrepr
を呼び出すからです(私はこれがPython 3の最大の設計上の欠陥の1つであると考えています)。実際のrepr
はおそらくprint [your, objects]
の出力としてあまり役に立ちません。
これを限定するために、私の経験では、repr
関数の最も有用な使用例は、(文字列フォーマットを使用して)別の文字列の中に文字列を入れることです。このように、あなたは引用符や何かをエスケープすることを心配する必要はありません。しかし、ここではeval
は発生していません。
簡単に言えば:
__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)
http://pyref.infogami.com/__str__ からeffbot:
__str__
はオブジェクトの「非公式な」文字列表現を計算します。これは有効なPython式である必要はないという点で__repr__
と異なります。代わりに、より便利な表現または簡潔な表現を使用できます。
他の答えで欠けている一面。一般的なパターンは次のとおりです。
__str__
の目的:人間が読めるもの__repr__
の目的:eval
を介した明確な、おそらく機械可読な残念なことに、Python REPLとIPythonはREPLコンソールでオブジェクトを印刷するために__repr__
を使うので、この区別に欠陥があります( Python と IPython)の関連質問を参照 )そのため、対話型コンソール作業(NumpyやPandasなど)を対象としたプロジェクトは、上記の規則を無視し、代わりに人間が読める__repr__
の実装を提供するようになりました。
str
- 与えられたオブジェクトから新しい文字列オブジェクトを作成します。
repr
- オブジェクトの正規の文字列表現を返します。
違い:
str():
repr():
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))
__str__
と__repr__
の違いはすでに優れた答えでカバーされています。これは、前者がエンドユーザーでも読み取り可能であること、そして後者が開発者にとってできるだけ有用であることを意味します。それを考えれば、__repr__
のデフォルトの実装では、この目的を達成できないことがよくあります。なぜなら、 は という情報を開発者にとって有用ではないからです。
このため、__str__
という単純なものがあれば、私は一般的に以下のような方法で両方の長所を最大限に活用しようとします。
def __repr__(self):
return '{0} ({1})'.format(object.__repr__(self), str(self))
"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
>>> 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インタプリタに渡されると(可能な場合)表現されたオブジェクトを再生成するような出力を生成するように設計されています。
覚えておくべき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__
、 "正式な" オブジェクトの表現を呼び出します。形式的表現は非公式の表現より読むのが難しいですが、それは明白でバグに対してより堅牢です。
手短に:
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'
__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
これがあなたがより多くの答えを探求するための具体的な根拠を築くのに役立つことを願っています。
__repr__
はprint
メソッドとstr
メソッド以外ではどこでも使用されます(__str__
が定義されている場合)。
__str__
は文字列オブジェクトを返さなければなりませんが、__repr__
は任意のpython式を返すことができます。__str__
の実装が欠けている場合は、__repr__
関数がフォールバックとして使用されます。 __repr__
関数の実装が欠けていてもフォールバックはありません。__repr__
関数がオブジェクトの文字列表現を返している場合は、__str__
関数の実装をスキップできます。ソース: https://www.journaldev.com/22460/python-str-repr-functions
__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