问题:__str__和__repr__之间的区别?
__str__
和__repr__
Python 和有什么不一样?
What is the difference between __str__
and __repr__
in Python?
回答 0
亚历克斯总结得很好,但令人惊讶的是,它太简洁了。
首先,让我重申亚历克斯(Alex)帖子中的要点:
- 默认的实现是无用的(很难想到不会的,但是是的)
__repr__
目标是明确
__str__
目标是可读
- 容器
__str__
使用的包含对象__repr__
默认实现是没有用的
这主要是令人惊讶的,因为Python的默认设置往往非常有用。但是,在这种情况下,具有默认值的__repr__
行为如下:
return "%s(%r)" % (self.__class__, self.__dict__)
太危险了(例如,如果对象之间互相引用,则很容易陷入无限递归)。因此,Python应对了。请注意,有一个默认值为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)
但是,您必须做最后一步-确保实现的每个对象都有一个有用的代表,这样的代码才能正常工作。这就是为什么出现“评估”问题的原因:如果您有足够的信息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__
如果您认为有一个字符串版本会影响可读性会很有用,请实施。
Alex summarized well but, surprisingly, was too succinct.
First, let me reiterate the main points in Alex’s post:
- The default implementation is useless (it’s hard to think of one which wouldn’t be, but yeah)
__repr__
goal is to be unambiguous
__str__
goal is to be readable
- Container’s
__str__
uses contained objects’ __repr__
Default implementation is useless
This is mostly a surprise because Python’s defaults tend to be fairly useful. However, in this case, having a default for __repr__
which would act like:
return "%s(%r)" % (self.__class__, self.__dict__)
would have been too dangerous (for example, too easy to get into infinite recursion if objects reference each other). So Python cops out. Note that there is one default which is true: if __repr__
is defined, and __str__
is not, the object will behave as though __str__=__repr__
.
This means, in simple terms: almost every object you implement should have a functional __repr__
that’s usable for understanding the object. Implementing __str__
is optional: do that if you need a “pretty print” functionality (for example, used by a report generator).
The goal of __repr__
is to be unambiguous
Let me come right out and say it — I do not believe in debuggers. I don’t really know how to use any debugger, and have never used one seriously. Furthermore, I believe that the big fault in debuggers is their basic nature — most failures I debug happened a long long time ago, in a galaxy far far away. This means that I do believe, with religious fervor, in logging. Logging is the lifeblood of any decent fire-and-forget server system. Python makes it easy to log: with maybe some project specific wrappers, all you need is a
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)
But you have to do the last step — make sure every object you implement has a useful repr, so code like that can just work. This is why the “eval” thing comes up: if you have enough information so eval(repr(c))==c
, that means you know everything there is to know about c
. If that’s easy enough, at least in a fuzzy way, do it. If not, make sure you have enough information about c
anyway. I usually use an eval-like format: "MyClass(this=%r,that=%r)" % (self.this,self.that)
. It does not mean that you can actually construct MyClass, or that those are the right constructor arguments — but it is a useful form to express “this is everything you need to know about this instance”.
Note: I used %r
above, not %s
. You always want to use repr()
[or %r
formatting character, equivalently] inside __repr__
implementation, or you’re defeating the goal of repr. You want to be able to differentiate MyClass(3)
and MyClass("3")
.
The goal of __str__
is to be readable
Specifically, it is not intended to be unambiguous — notice that str(3)==str("3")
. Likewise, if you implement an IP abstraction, having the str of it look like 192.168.1.1 is just fine. When implementing a date/time abstraction, the str can be “2010/4/12 15:35:22”, etc. The goal is to represent it in a way that a user, not a programmer, would want to read it. Chop off useless digits, pretend to be some other class — as long is it supports readability, it is an improvement.
Container’s __str__
uses contained objects’ __repr__
This seems surprising, doesn’t it? It is a little, but how readable would it be if it used their __str__
?
[moshe is, 3, hello
world, this is a list, oh I don't know, containing just 4 elements]
Not very. Specifically, the strings in a container would find it way too easy to disturb its string representation. In the face of ambiguity, remember, Python resists the temptation to guess. If you want the above behavior when you’re printing a list, just
print "[" + ", ".join(l) + "]"
(you can probably also figure out what to do about dictionaries.
Summary
Implement __repr__
for any class you implement. This should be second nature. Implement __str__
if you think it would be useful to have a string version which errs on the side of readability.
回答 1
我的经验法则: __repr__
针对开发人员,__str__
针对客户。
My rule of thumb: __repr__
is for developers, __str__
is for customers.
回答 2
除非您特别采取行动以确保其他情况,否则大多数类在以下两个方面均不会产生有用的结果:
>>> class Sic(object): pass
...
>>> print str(Sic())
<__main__.Sic object at 0x8b7d0>
>>> print repr(Sic())
<__main__.Sic object at 0x8b7d0>
>>>
如您所见-没有区别,没有信息超出类和对象的id
。如果仅覆盖两个…之一:
>>> 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__
!的模糊不可实现的目标。
Unless you specifically act to ensure otherwise, most classes don’t have helpful results for either:
>>> class Sic(object): pass
...
>>> print str(Sic())
<__main__.Sic object at 0x8b7d0>
>>> print repr(Sic())
<__main__.Sic object at 0x8b7d0>
>>>
As you see — no difference, and no info beyond the class and object’s id
. If you only override one of the two…:
>>> 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>
>>>
as you see, if you override __repr__
, that’s ALSO used for __str__
, but not vice versa.
Other crucial tidbits to know: __str__
on a built-on container uses the __repr__
, NOT the __str__
, for the items it contains. And, despite the words on the subject found in typical docs, hardly anybody bothers making the __repr__
of objects be a string that eval
may use to build an equal object (it’s just too hard, AND not knowing how the relevant module was actually imported makes it actually flat out impossible).
So, my advice: focus on making __str__
reasonably human-readable, and __repr__
as unambiguous as you possibly can, even if that interferes with the fuzzy unattainable goal of making __repr__
‘s returned value acceptable as input to __eval__
!
回答 3
__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
__repr__
: representation of python object usually eval will convert it back to that object
__str__
: is whatever you think is that object in text form
e.g.
>>> 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
回答 4
简而言之,的目标__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(object)
返回包含对象的可打印表示形式的字符串。这与转化产生的值相同(反引号)。能够以常规功能访问此操作有时很有用。对于许多类型,此函数会尝试返回一个字符串,该字符串将在传递给时产生一个具有相同值的对象eval()
,否则表示形式是一个用尖括号括起来的字符串,其中包含对象类型的名称以及其他信息通常包括对象的名称和地址。类可以通过定义__repr__()
方法来控制此函数为其实例返回的内容。
这是str的文档:
str(object='')
返回一个字符串,其中包含对象的可很好打印的表示形式。对于字符串,这将返回字符串本身。与的区别repr(object)
在于,str(object)
并非总是尝试返回可接受的字符串eval()
;它的目标是返回可打印的字符串。如果未提供任何参数,则返回空字符串''
。
In short, the goal of __repr__
is to be unambiguous and __str__
is to be
readable.
Here is a good example:
>>> 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)'
Read this documentation for repr:
repr(object)
Return a string containing a printable representation of an object. This is the same value yielded by conversions (reverse
quotes). It is sometimes useful to be able to access this operation as
an ordinary function. For many types, this function makes an attempt
to return a string that would yield an object with the same value when
passed to eval()
, otherwise the representation is a string enclosed in
angle brackets that contains the name of the type of the object
together with additional information often including the name and
address of the object. A class can control what this function returns
for its instances by defining a __repr__()
method.
Here is the documentation for str:
str(object='')
Return a string containing a nicely printable
representation of an object. For strings, this returns the string
itself. The difference with repr(object)
is that str(object)
does not
always attempt to return a string that is acceptable to eval()
; its
goal is to return a printable string. If no argument is given, returns
the empty string, ''
.
回答 5
__str__
和__repr__
Python 和有什么不一样?
__str__
(读为“ dunder(双下划线)字符串”)和__repr__
(读为“ dunder-repper”(对于“表示形式”))都是根据对象状态返回字符串的特殊方法。
__repr__
如果__str__
丢失,则提供备份行为。
因此,首先应该编写一个__repr__
,使您可以从返回的字符串中重新实例化一个等效的对象,例如,使用eval
或通过在Python Shell中的逐字符键入字符。
在以后的任何时候,只要__str__
有人认为有必要,就可以为该实例的用户可读的字符串表示形式编写一个。
__str__
如果打印对象,或将其传递给format
,str.format
或str
,则如果__str__
定义了方法,则将调用该方法,否则__repr__
将使用该方法。
__repr__
该__repr__
方法由内置函数调用,repr
并且是在评估返回对象的表达式时在python shell上回显的方法。
由于它为提供了备份__str__
,如果您只能写一个,请从__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)))
这意味着默认情况下,您将打印对象所属的模块,类名以及其在内存中位置的十六进制表示形式,例如:
<__main__.Foo object at 0x7f80665abdd0>
这些信息不是很有用,但是无法得出如何准确地创建任何给定实例的规范表示的方法,它总比没有好,至少告诉我们如何在内存中唯一标识它。
怎么__repr__
有用?
让我们看看使用Python Shell和datetime
对象有多么有用。首先,我们需要导入datetime
模块:
import datetime
如果datetime.now
在外壳中调用,我们将看到重新创建等效的datetime对象所需的一切。这是由datetime创建的__repr__
:
>>> datetime.datetime.now()
datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)
如果我们打印日期时间对象,则会看到一种很好的人类可读(实际上是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源)。由于复制此类对象所需的所有属性,它相当复杂:
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__
在编写a之前应先写一个供开发人员在调试中使用的a __str__
。
你需要一个__str__
只有当你需要的对象的文本表示。
结论
__repr__
为您编写的对象进行定义,以便您和其他开发人员在开发过程中使用它时可以得到一个可重现的示例。定义__str__
何时需要其人类可读的字符串表示形式。
What is the difference between __str__
and __repr__
in Python?
__str__
(read as “dunder (double-underscore) string”) and __repr__
(read as “dunder-repper” (for “representation”)) are both special methods that return strings based on the state of the object.
__repr__
provides backup behavior if __str__
is missing.
So one should first write a __repr__
that allows you to reinstantiate an equivalent object from the string it returns e.g. using eval
or by typing it in character-for-character in a Python shell.
At any time later, one can write a __str__
for a user-readable string representation of the instance, when one believes it to be necessary.
__str__
If you print an object, or pass it to format
, str.format
, or str
, then if a __str__
method is defined, that method will be called, otherwise, __repr__
will be used.
__repr__
The __repr__
method is called by the builtin function repr
and is what is echoed on your python shell when it evaluates an expression that returns an object.
Since it provides a backup for __str__
, if you can only write one, start with __repr__
Here’s the builtin help on repr
:
repr(...)
repr(object) -> string
Return the canonical string representation of the object.
For most object types, eval(repr(object)) == object.
That is, for most objects, if you type in what is printed by repr
, you should be able to create an equivalent object. But this is not the default implementation.
Default Implementation of __repr__
The default object __repr__
is (C Python source) something like:
def __repr__(self):
return '<{0}.{1} object at {2}>'.format(
self.__module__, type(self).__name__, hex(id(self)))
That means by default you’ll print the module the object is from, the class name, and the hexadecimal representation of its location in memory – for example:
<__main__.Foo object at 0x7f80665abdd0>
This information isn’t very useful, but there’s no way to derive how one might accurately create a canonical representation of any given instance, and it’s better than nothing, at least telling us how we might uniquely identify it in memory.
How can __repr__
be useful?
Let’s look at how useful it can be, using the Python shell and datetime
objects. First we need to import the datetime
module:
import datetime
If we call datetime.now
in the shell, we’ll see everything we need to recreate an equivalent datetime object. This is created by the datetime __repr__
:
>>> datetime.datetime.now()
datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)
If we print a datetime object, we see a nice human readable (in fact, ISO) format. This is implemented by datetime’s __str__
:
>>> print(datetime.datetime.now())
2015-01-24 20:05:44.977951
It is a simple matter to recreate the object we lost because we didn’t assign it to a variable by copying and pasting from the __repr__
output, and then printing it, and we get it in the same human readable output as the other object:
>>> the_past = datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)
>>> print(the_past)
2015-01-24 20:05:36.491180
How do I implement them?
As you’re developing, you’ll want to be able to reproduce objects in the same state, if possible. This, for example, is how the datetime object defines __repr__
(Python source). It is fairly complex, because of all of the attributes needed to reproduce such an object:
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
If you want your object to have a more human readable representation, you can implement __str__
next. Here’s how the datetime object (Python source) implements __str__
, which it easily does because it already has a function to display it in ISO format:
def __str__(self):
"Convert to string, for str()."
return self.isoformat(sep=' ')
Set __repr__ = __str__
?
This is a critique of another answer here that suggests setting __repr__ = __str__
.
Setting __repr__ = __str__
is silly – __repr__
is a fallback for __str__
and a __repr__
, written for developers usage in debugging, should be written before you write a __str__
.
You need a __str__
only when you need a textual representation of the object.
Conclusion
Define __repr__
for objects you write so you and other developers have a reproducible example when using it as you develop. Define __str__
when you need a human readable string representation of it.
回答 6
在Hans Petter Langtangen 撰写的《用于计算科学的Python脚本》一书的第358页中,明确指出:
- 所述
__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'
On page 358 of the book Python scripting for computational science by Hans Petter Langtangen, it clearly states that
- The
__repr__
aims at a complete string representation of the object;
- The
__str__
is to return a nice string for printing.
So, I prefer to understand them as
- repr = reproduce
- str = string (representation)
from the user’s point of view
although this is a misunderstanding I made when learning python.
A small but good example is also given on the same page as follows:
Example
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'
回答 7
除了给出的所有答案外,我想补充几点:
__repr__()
当您在交互式python控制台上简单地写对象名称并按Enter时,将调用1)。
2)__str__()
在带print语句的对象上使用时被调用。
3)如果__str__
丢失,则打印并使用对象str()
调用__repr__()
进行任何功能。
4)__str__()
容器,当被调用时将执行__repr__()
其所包含元素的方法。
5)str()
在内部调用__str__()
可能会在没有基本情况的情况下递归,并且最大递归深度会出错。
6)__repr__()
可以调用repr()
,它将尝试自动避免无限递归,将表示的对象替换为...
。
Apart from all the answers given, I would like to add few points :-
1) __repr__()
is invoked when you simply write object’s name on interactive python console and press enter.
2) __str__()
is invoked when you use object with print statement.
3) In case, if __str__
is missing, then print and any function using str()
invokes __repr__()
of object.
4) __str__()
of containers, when invoked will execute __repr__()
method of its contained elements.
5) str()
called within __str__()
could potentially recurse without a base case, and error on maximum recursion depth.
6) __repr__()
can call repr()
which will attempt to avoid infinite recursion automatically, replacing an already represented object with ...
.
回答 8
老实说,eval(repr(obj))
从未使用过。如果发现自己正在使用它,则应该停止操作,因为这样做eval
很危险,而字符串是序列化对象(pickle
替代使用)的效率很低的方法。
因此,我建议设置__repr__ = __str__
。原因是str(list)
调用repr
元素(我认为这是Python 3未能解决的Python最大设计缺陷之一)。实际repr
输出可能不会非常有用print [your, objects]
。
为了证明这一点,以我的经验,该repr
函数最有用的用例是将一个字符串放入另一个字符串中(使用字符串格式)。这样,您不必担心转义引号或其他内容。但是请注意,这里没有eval
发生任何事情。
In all honesty, eval(repr(obj))
is never used. If you find yourself using it, you should stop, because eval
is dangerous, and strings are a very inefficient way to serialize your objects (use pickle
instead).
Therefore, I would recommend setting __repr__ = __str__
. The reason is that str(list)
calls repr
on the elements (I consider this to be one of the biggest design flaws of Python that was not addressed by Python 3). An actual repr
will probably not be very helpful as the output of print [your, objects]
.
To qualify this, in my experience, the most useful use case of the repr
function is to put a string inside another string (using string formatting). This way, you don’t have to worry about escaping quotes or anything. But note that there is no eval
happening here.
回答 9
简而言之:
__str__
用于显示对象的字符串表示形式,以方便他人阅读。
__repr__
用于显示的字符串表示的对象。
假设我要创建一个Fraction
类,其中分数的字符串表示形式为“(1/2)”,而对象(分数类)将表示为“分数(1,2)”
因此,我们可以创建一个简单的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)
To put it simply:
__str__
is used in to show a string representation of your object to be read easily by others.
__repr__
is used to show a string representation of the object.
Let’s say I want to create a Fraction
class where the string representation of a fraction is ‘(1/2)’ and the object (Fraction class) is to be represented as ‘Fraction (1,2)’
So we can create a simple Fraction class:
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)
回答 10
From an (An Unofficial) Python Reference Wiki (archive copy) by effbot:
__str__
“computes the “informal” string representation of an object. This differs from __repr__
in that it does not have to be a valid Python expression: a more convenient or concise representation may be used instead.“
回答 11
str
-从给定的对象创建一个新的字符串对象。
repr
-返回对象的规范字符串表示形式。
区别:
str():
repr():
str
– Creates a new string object from the given object.
repr
– Returns the canonical string representation of the object.
The differences:
str():
- makes object readable
- generates output for end-user
repr():
- needs code that reproduces object
- generates output for developer
回答 12
其他答案中缺少的一个方面。的确,该模式通常是:
- 目标
__str__
:人类可读
- 目标
__repr__
:明确,可能通过机器读取eval
不幸的是,这种区别是有缺陷的,因为Python REPL和IPython都__repr__
用于在REPL控制台中打印对象(请参阅Python和IPython的相关问题)。因此,以交互式控制台工作为目标的项目(例如Numpy或Pandas)已经开始忽略上述规则,__repr__
而是提供了易于理解的实现方式。
One aspect that is missing in other answers. It’s true that in general the pattern is:
- Goal of
__str__
: human-readable
- Goal of
__repr__
: unambiguous, possibly machine-readable via eval
Unfortunately, this differentiation is flawed, because the Python REPL and also IPython use __repr__
for printing objects in a REPL console (see related questions for Python and IPython). Thus, projects which are targeted for interactive console work (e.g., Numpy or Pandas) have started to ignore above rules and provide a human-readable __repr__
implementation instead.
回答 13
摘自Fluent Python一书:
Python对象的基本要求是提供其自身的可用字符串表示形式,一种用于调试和记录,另一种用于呈现给最终用户。这就是为什么
特殊方法__repr__
和__str__
存在于数据模型中的原因。
From the book Fluent Python:
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.
回答 14
出色的答案已经涵盖了__str__
和之间的区别__repr__
,对我而言,这归结为前者甚至对于最终用户而言都是可读的,而后者对开发人员则尽可能有用。鉴于此,我发现的默认实现__repr__
常常无法实现此目标,因为它忽略了对开发人员有用的信息。
出于这个原因,如果我有一个简单的方法__str__
,我通常会尝试通过以下方法使两个方面都达到最佳:
def __repr__(self):
return '{0} ({1})'.format(object.__repr__(self), str(self))
Excellent answers already cover the difference between __str__
and __repr__
, which for me boils down to the former being readable even by an end user, and the latter being as useful as possible to developers. Given that, I find that the default implementation of __repr__
often fails to achieve this goal because it omits information useful to developers.
For this reason, if I have a simple enough __str__
, I generally just try to get the best of both worlds with something like:
def __repr__(self):
return '{0} ({1})'.format(object.__repr__(self), str(self))
回答 15
要记住的重要一件事是容器的__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主张明确性胜于可读性,__str__
调用tuple
调用包含的对象’ __repr__
,即对象的“正式”表示形式。尽管正式表示比非正式表示更难读,但它对歧义没有任何歧义,并且更强大。
One important thing to keep in mind is that container’s __str__
uses contained objects’ __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 favors unambiguity over readability, the __str__
call of a tuple
calls the contained objects’ __repr__
, the “formal” representation of an object. Although the formal representation is harder to read than an informal one, it is unambiguous and more robust against bugs.
回答 16
简而言之:
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'
In a nutshell:
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'
回答 17
>>> 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对象都有两种输出形式。字符串形式被设计为易于阅读。表示形式旨在产生输出,如果将其提供给Python解释器,则该输出将(如果可能)再现所表示的对象。
>>> print(decimal.Decimal(23) / decimal.Decimal("1.05"))
21.90476190476190476190476190
>>> decimal.Decimal(23) / decimal.Decimal("1.05")
Decimal('21.90476190476190476190476190')
When print()
is called on the result of decimal.Decimal(23) / decimal.Decimal("1.05")
the raw number is printed; this output is in string form which can be achieved with __str__()
. If we simply enter the expression we get a decimal.Decimal
output — this output is in representational form which can be achieved with __repr__()
. All Python objects have two output forms. String form is designed to be human-readable. The representational form is designed to produce output that if fed to a Python interpreter would (when possible) reproduce the represented object.
回答 18
__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
__str__
can be invoked on an object by calling str(obj)
and should return a human readable string.
__repr__
can be invoked on an object by calling repr(obj)
and should return internal object (object fields/attributes)
This example may help:
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
回答 19
理解__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
希望这可以帮助您建立具体的基础,以探索更多的答案。
Understand __str__
and __repr__
intuitively and permanently distinguish them at all.
__str__
return the string disguised body of a given object for readable of eyes
__repr__
return the real flesh body of a given object (return itself) for unambiguity to identify.
See it in an example
In [30]: str(datetime.datetime.now())
Out[30]: '2017-12-07 15:41:14.002752'
Disguised in string form
As to __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.
We can do arithmetic operation on __repr__
results conveniently.
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)
if apply the operation on __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'
Returns nothing but error.
Another example.
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
Hope this help you build concrete grounds to explore more answers.
回答 20
__str__
must return string object whereas __repr__
can return any python expression.
- If
__str__
implementation is missing then __repr__
function is used as fallback. There is no fallback if __repr__
function implementation is missing.
- If
__repr__
function is returning String representation of the object, we can skip implementation of __str__
function.
Source: https://www.journaldev.com/22460/python-str-repr-functions
回答 21
__repr__
用于除print
和str
方法(__str__
定义a时!)之外的所有地方
__repr__
is used everywhere, except by print
and str
methods (when a __str__
is defined !)