__str__和__repr__之间的区别?

Cas*_*ash 2545 python repr magic-methods

之间有什么区别__str____repr____str__

mos*_*hez 2590

亚历克斯总结得很好,但令人惊讶的是,它太简洁了.

首先,让我重申Alex的帖子中的要点:

  • 默认实现是无用的(很难想到一个不会,但是是的)
  • __repr__ 目标是明确的
  • __str__ 目标是可读的
  • 容器的__str__用途包含对象'__repr__

默认实现是无用的

这主要是一个惊喜,因为Python的默认值往往非常有用.但是,在这种情况下,具有默认值的__repr__行为如下:

return "%s(%r)" % (self.__class__, self.__dict__)
Run Code Online (Sandbox Code Playgroud)

本来就太危险了(例如,如果对象相互引用,太容易进入无限递归).所以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)
Run Code Online (Sandbox Code Playgroud)

但是你必须做最后一步 - 确保你实现的每个对象都有一个有用的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__

这似乎令人惊讶,不是吗?它有点,但可读性如何

[moshe is, 3, hello
world, this is a list, oh I don't know, containing just 4 elements]
Run Code Online (Sandbox Code Playgroud)

是?不是特别的.具体来说,容器中的字符串会发现太容易打扰它的字符串表示.面对模棱两可,请记住,Python抵制猜测的诱惑.如果您在打印列表时想要上述行为,请执行

print "[" + ", ".join(l) + "]"
Run Code Online (Sandbox Code Playgroud)

(你也可以弄清楚如何处理词典.

摘要

实现__repr__您实现的任何类.这应该是第二天性.实现__str__,如果你认为这将是具有犯错可读性侧面的字符串版本是有用的.

  • 绝对不同意您的意见,调试不是要走的路.对于开发,使用调试器(和/或日志记录),用于生产使用日志记录.使用调试器,您可以查看问题发生时出错的所有内容.你可以看到完整的图片.除非你记录一切,否则你无法得到它.此外,如果您要记录所有内容,那么您需要通过大量数据来获取所需内容. (119认同)
  • 很好的答案(除了关于不使用调试器的一点).我只想添加一个链接到[关于_3tr__与Python 3中的__unicode__的其他问答](http://stackoverflow.com/questions/1307014/python-str-versus-unicode),这可能与讨论有关对于那些做出转变的人. (17认同)
  • 调试器的plus1是无用的,并且不值一毛钱.而是提高您的日志吞吐量.是的,这是一篇写得很好的帖子.事实证明`__repr__`是我调试所需要的.谢谢您的帮助. (9认同)
  • 除了调试器之外,我还学会了%r,这还是值得一票的 (7认同)
  • Python 3 最新版本的一个小更新:您可以使用 f 字符串,并且仍然通过添加 `!r` 来调用您嵌入的数据的 `__repr__`:您可以替换 `"MyClass(this=%r,that=% r)" % (self.this,self.that)` by `f"MyClass(this={self.this!r},that={self.that!r})"`。否则,感谢这篇精彩的文章! (7认同)
  • 关于调试器与没有调试器:不要得到这种根深蒂固的意见。在某些应用程序中,调试是不现实的,通常是在涉及实时的情况下,或者当您的代码仅在几乎没有访问权限或没有控制台的平台上远程执行时。在大多数其他情况下,停止异常进行调查或设置断点将更快,因为您不必执行数千行的日志记录(这会使磁盘混乱并使应用程序变慢)。最后,并非总是可以登录,例如在嵌入式设备上,调试器也是您的朋友。 (4认同)
  • 关于调试与日志记录,它们都很有用。如果错误是可重现的,则调试会更简单。如果错误是随机的,则日志记录至关重要。 (2认同)
  • “我不相信调试器。我真的不知道如何使用任何调试器”——这让我大笑,让我想起南方公园的一集,那家伙从未尝试过毒品,因此他确信毒品是邪恶的。我想我们都害怕未知。 (2认同)

Ned*_*der 480

我的经验法则__repr__是: 适用于开发人员,__str__适用于客户.

  • 这是真的,因为对于 obj = uuid.uuid1(),obj.__str__() 是“2d7fc7f0-7706-11e9-94ae-0242ac110002”,而 obj.__repr__() 是“UUID('2d7fc7f0-7906-420e10-7706-11e1 ')”。开发人员需要(价值 + 来源),而客户需要价值,他们不在乎他们是如何得到的! (10认同)
  • 这里的“客户”不一定是指最终用户。它是对象的客户端或用户。因此,如果它是一个 SDK,那么 SDK 开发人员将使用“__str__”,这样普通开发人员就有可读的对象。另一方面,`__repr__`是为SDK开发者自己准备的。 (7认同)

Ale*_*lli 380

除非您特别采取行动以确保其他方面,否则大多数课程都没有任何有用的结果:

>>> class Sic(object): pass
... 
>>> print str(Sic())
<__main__.Sic object at 0x8b7d0>
>>> print repr(Sic())
<__main__.Sic object at 0x8b7d0>
>>> 
Run Code Online (Sandbox Code Playgroud)

如你所见 - 没有区别,也没有超出类和对象的信息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>
>>> 
Run Code Online (Sandbox Code Playgroud)

如你所见,如果你覆盖__repr__,那也是用于__str__,但反之亦然.

要知道的其他重要花絮:__str__在内置容器上使用__repr__,而不是__str__它包含的项目.而且,尽管在典型的文档中找到了关于主题的文字,但几乎没有人会把__repr__对象变成一个eval可能用来构建一个平等对象的字符串(它太难了,而且不知道相关模块是如何实际导入的完全不可能).

因此,我的建议是:专注于制作__str__合理的人类可读性,并__repr__尽可能明确无误,即使这会干扰模糊的无法实现的目标,__repr__即将返回值作为输入来接受__eval__!

  • 在我的单元测试中,我总是检查`eval(repr(foo))`对一个等于`foo`的对象进行求值.你是对的,它不会在我的测试用例之外工作,因为我不知道如何导入模块,但这至少可以确保它在_some_ predictable context中工作.我认为这是评估`__repr__`的结果是否足够明确的好方法.在单元测试中执行此操作还有助于确保`__repr__`跟随对类的更改. (31认同)
  • 我总是试图确保`eval(repr(spam))== spam`(至少在正确的上下文中)或`eval(repr(spam))`引发`SyntaxError`.这样你就可以避免混淆.(对于内置函数和大多数stdlib来说,_almost_为true,除了例如递归列表,其中`a = []; a.append(a); print(eval(repr(a)))`给你` [[Ellipses]]`...)当然我不这样做实际_use_`eval(repr(垃圾))`,除了作为单元测试中的健全性检查...但我有时复制并粘贴`repr(垃圾邮件) `进入互动环节. (2认同)
  • @abarnert:对于自定义“class Spam”,“eval(repr(spam)) == spam”也需要实现“Spam.__eq__”,对吗?默认情况下 `object.__eq__` 使用 `is` ([docs](https://docs.python.org/3/reference/datamodel.html#object.__eq__))。 (2认同)

小智 159

__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
Run Code Online (Sandbox Code Playgroud)

  • __repr__() :用于在字符串中创建“类似构造函数的表达式”,以便 eval() 可以从此字符串表示形式重新构造对象 __str__() :用于创建包含对象的可打印表示形式的字符串 (3认同)

bit*_*dev 142

简而言之,目标__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)'
Run Code Online (Sandbox Code Playgroud)

阅读此文档以获取repr:

repr(object)

返回包含对象的可打印表示的字符串.这与转换(反向引号)产生的值相同.能够以普通函数的形式访问此操作有时很有用.对于许多类型,此函数尝试返回一个字符串,该字符串在传递时会产生具有相同值的对象eval(),否则表示形式是一个括在尖括号中的字符串,其中包含对象类型的名称以及其他信息通常包括对象的名称和地址.类可以通过定义__repr__()方法来控制此函数为其实例返回的内容.

这是str的文档:

str(object='')

返回一个包含对象的可打印表示的字符串.对于字符串,这将返回字符串本身.与之不同的repr(object)是,str(object)并不总是尝试返回可接受的字符串eval(); 它的目标是返回一个可打印的字符串.如果没有给出参数,则返回空字符串,''.

  • 这里的可打印字符串是什么意思?你能解释一下吗? (2认同)
  • 在上面的“bitoffdev”和@deadly示例的基础上,我们可以看到 __str__ 对于最终用户来说是如何的,因为它只为我们提供了一个可读的字符串,而 __repr__ 对于开发人员来说是因为它为我们提供了值和类型。如果您正在寻找面试答案,那么这将是完美的。 (2认同)

Aar*_*all 109

__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.
Run Code Online (Sandbox Code Playgroud)

也就是说,对于大多数对象,如果键入打印的内容repr,则应该能够创建等效对象.但这不是默认实现.

默认实现 __repr__

默认对象__repr__是(C Python源代码),例如:

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

这意味着默认情况下,您将打印对象所在的模块,类名以及其在内存中的位置的十六进制表示形式 - 例如:

<__main__.Foo object at 0x7f80665abdd0>
Run Code Online (Sandbox Code Playgroud)

这些信息不是很有用,但是没有办法得出如何准确地创建任何给定实例的规范表示,并且它总比没有好,至少告诉我们如何在内存中唯一地识别它.

怎么__repr__有用?

让我们看一下使用Python shell和datetime对象有多么有用.首先我们需要导入datetime模块:

import datetime
Run Code Online (Sandbox Code Playgroud)

如果我们调用datetime.nowshell,我们将看到重新创建等效的datetime对象所需的一切.这是由datetime创建的__repr__:

>>> datetime.datetime.now()
datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)
Run Code Online (Sandbox Code Playgroud)

如果我们打印一个日期时间对象,我们会看到一个很好的人类可读(实际上是ISO)格式.这是由datetime实现的__str__:

>>> print(datetime.datetime.now())
2015-01-24 20:05:44.977951
Run Code Online (Sandbox Code Playgroud)

重新创建我们丢失的对象是一件简单的事情,因为我们没有通过从__repr__输出复制和粘贴,然后打印它来将它分配给变量,我们将它与另一个对象放在相同的人类可读输出中:

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

我该如何实现它们?

在开发过程中,如果可能的话,您将希望能够以相同的状态再现对象.例如,这是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
Run Code Online (Sandbox Code Playgroud)

如果您希望对象具有更易于阅读的表示形式,则可以执行__str__下一步.以下是datetime对象(Python源代码)的实现方式__str__,它很容易实现,因为它已经具有以ISO格式显示它的函数:

def __str__(self):
    "Convert to string, for str()."
    return self.isoformat(sep=' ')
Run Code Online (Sandbox Code Playgroud)

设置__repr__ = __str__

这是对这里建议设定的另一个答案的批评__repr__ = __str__.

设置__repr__ = __str__是愚蠢的 - __repr__是一个后备__str__和a __repr__,为开发人员在调试中使用而编写,应该在你编写之前编写__str__.

你需要__str__的时候,你所需要的对象的文本表示只.

结论

定义__repr__您编写的对象,以便您和其他开发人员在开发时使用它时具有可重现的示例.定义__str__何时需要人类可读的字符串表示形式.


小智 26

在Hans Petter Langtangen 的" Python脚本编程 "一书的第358页上,它清楚地表明了这一点

  • 所述__repr__在所述物体的完整字符串表示目标;
  • __str__是返回一个字符串精美印刷.

所以,我更喜欢将它们理解为

  • repr =重现
  • str = string(表示)

从用户的角度来看虽然这是我在学习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'
Run Code Online (Sandbox Code Playgroud)

  • 将 `repr` 称为再现有点误导。最好将其视为代表。 (7认同)

Man*_*hit 25

除了给出的所有答案外,我想补充几点:

1)__repr__()只需在交互式python控制台上编写对象名称并按Enter键即可调用.

2)__str__()在使用带有print语句的对象时调用.

3)如果__str__缺少,则使用对象str()调用打印和任何函数__repr__().

4)__str__()容器,当被调用时将执行__repr__()其包含元素的方法.

5)str()内部调用__str__()可能在没有基本情况下递归,并且在最大递归深度上出错.

6)__repr__()可以调用repr()哪个将尝试自动避免无限递归,用已替换已经表示的对象....


asm*_*rer 12

老实说,eval(repr(obj))从未使用过.如果你发现自己使用它,你应该停止,因为它eval是危险的,并且字符串是一种非常低效的序列化对象的方式(pickle改为使用).

因此,我建议设置__repr__ = __str__.原因是对元素的str(list)调用repr(我认为这是Python 3中没有解决的Python最大的设计缺陷之一).repr作为输出,实际可能不会非常有用print [your, objects].

为了限定这一点,根据我的经验,该repr函数最有用的用例是将一个字符串放在另一个字符串中(使用字符串格式).这样,您不必担心转义引号或任何内容.但请注意,这里没有eval发生.

  • 我认为这忽略了这一点.使用`eval(repr(obj))`是一个健全性测试和经验法则 - 如果这正确地重新创建原始对象,那么你有一个体面的`__repr__`实现.并不打算以这种方式实际序列化对象. (19认同)
  • `eval`本身并不危险.并不比`unlink`,`open`或写入文件更危险.我们是否应该停止写入文件,因为恶意攻击可能会使用任意文件路径将内容放入其中?如果愚蠢的人愚蠢地使用,一切都是危险的.白痴是危险的.Dunning-Kruger效果很危险.`eval`只是一个功能. (6认同)

Zer*_*er0 11

简而言之:

__str__用于显示对象的字符串表示形式,以供其他人轻松阅读.

__repr__用于显示的字符串表示对象.

假设我想创建一个Fraction类,其中分数的字符串表示为'(1/2)',对象(Fraction类)将表示为'Fraction(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)
Run Code Online (Sandbox Code Playgroud)


Cas*_*ash 10

来自effbot的http://pyref.infogami.com/__str__:

__str__"计算对象的"非正式"字符串表示.这不同于__repr__它不必是有效的Python表达式:可以使用更方便或简洁的表示."

  • `__repr__`绝不需要返回一个vaild Python表达式. (3认同)

wes*_*cpy 10

问:这有什么区别__str__()__repr__()

特尔;博士: str()/repr() 和 __str__()/__repr__() 的区别

这个问题已经存在很长时间了,并且有各种各样的答案,其中大多数是正确的(更不用说来自几个 Python 社区传奇[!])。然而,归根结底,这个问题类似于询问内置函数str()repr()内置函数之间的区别。我将用我自己的话来描述这些差异(这意味着我可能会从Core Python Programming 中大量“借用”,所以请原谅我)。

双方 str()repr()具有相同的基本任务:他们的目标是返回一个Python对象的字符串表示。什么的字符串表示是区分它们的原因。

  • str()&__str__()返回一个对象的可打印字符串表示......人类可读/供人类消费的东西
  • repr()&__repr__()返回一个对象的字符串表示形式,该对象是一个 有效的 Python 对象,您可以将其传递给eval()或输入到 Python shell 中而不会出错。

例如,让我们分配一个字符串 tox和一个intto y,并简单地显示每个的人类可读的字符串版本:

>>> x, y = 'foo', 123
>>> str(x), str(y)
('foo', '123')
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,我们能否将引号内的内容逐字输入到 Python 解释器中?试一试吧:

>>> 123
123
>>> foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'foo' is not defined
Run Code Online (Sandbox Code Playgroud)

显然,您可以为 anint但不一定为 a str。虽然我可以传递'123'eval(),但这不适用于'foo'

>>> eval('123')
123
>>> eval('foo')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name 'foo' is not defined
Run Code Online (Sandbox Code Playgroud)

现在让我们试试repr();再次,转储每个字符串的引号对中的内容:

>>> repr(x), repr(y)
("'foo'", '123')
>>> 123
123
>>> 'foo'
'foo'
Run Code Online (Sandbox Code Playgroud)

哇,他们工作?那是因为'foo',虽然该字符串的可打印字符串表示形式,但它不是可评估的,而是"'foo'"可评估的。123intstr()或调用的有效 Python repr()。当我们eval()用这些调用时会发生什么?

>>> eval('123')
123
>>> eval("'foo'")
'foo'
Run Code Online (Sandbox Code Playgroud)

它有效,因为123并且'foo'是有效的 Python 对象。另一个关键要点是,虽然有时两者都返回相同的内容(相同的字符串表示),但情况并非总是如此。(是的,是的,我可以去创建一个变量foo,其中eval()的作品,但是,这不是问题的关键。)

关于这两对的更多事实

  1. 有时,str()并且repr()隐式调用,这意味着它们是代表用户调用的:当用户执行print(Py1/Py2) 或调用print()(Py3+) 时,即使用户没有str()显式调用,这样的调用也会在调用之前代表他们进行对象显示。
  2. 在 Python shell(交互式解释器)中,如果您在>>>提示符下输入一个变量并按 RETURN 键,解释器将显示repr()对该对象隐式调用的结果。
  3. 要连接str()repr()__str__()__repr__(),实现对内置函数的调用,即,str(x)repr(y)导致调用其对象的相应特殊方法:x.__str__()y.__repr()__
  4. 通过为Python 类实现__str__()__repr__()可以重载内置函数(str()repr()),从而允许将类的实例传递给str()repr()。当进行这样的调用时,他们转过身来调用类'__str__()__repr__()(根据#3)。


Jon*_*bie 10

您可以从这段代码中获得一些见解:

class Foo:
    def __repr__(self):
        return "repr"

    def __str__(self):
        return "str"

foo = Foo()
foo  # repr
print(foo)  # str
Run Code Online (Sandbox Code Playgroud)


pro*_*sti 9

__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
Run Code Online (Sandbox Code Playgroud)


Inc*_*nnu 7

str - 从给定对象创建新的字符串对象.

repr - 返回对象的规范字符串表示形式.

差异:

STR():

  • 使对象可读
  • 为最终用户生成输出

再版():

  • 需要复制对象的代码
  • 为开发人员生成输出


blu*_*e10 7

其他答案中缺少一个方面.的确,一般来说,模式是:

  • 目标__str__:人类可读
  • 目标__repr__:明确,可能是机器可读的通道eval

不幸的是,这种差异是有缺陷的,因为Python REPL和IPython __repr__用于在REPL控制台中打印对象(参见PythonIPython的相关问题).因此,针对交互式控制台工作的项目(例如,Numpy或Pandas)已开始忽略上述规则并提供人类可读的__repr__实现.


Bat*_*rum 6

>>> print(decimal.Decimal(23) / decimal.Decimal("1.05"))\n21.90476190476190476190476190\n>>> decimal.Decimal(23) / decimal.Decimal("1.05")\nDecimal(\'21.90476190476190476190476190\')\n
Run Code Online (Sandbox Code Playgroud)\n\n

When被调用,原始数字print()的结果被打印;decimal.Decimal(23) / decimal.Decimal("1.05")该输出是字符串形式,可以使用__str__(). 如果我们简单地输入表达式,我们会得到一个decimal.Decimal输出 \xe2\x80\x94,该输出采用表示形式,可以使用 来实现__repr__()。所有 Python 对象都有两种输出形式。字符串形式被设计为人类可读的。表征形式旨在产生输出,如果将其输入到 Python 解释器,将(在可能的情况下)再现所表征的对象。

\n


oro*_*ome 5

优秀的答案已经涵盖了__str__和之间的区别__repr__,对我来说,这归结为前者即使最终用户也可以阅读,而后者对开发人员尽可能有用。鉴于此,我发现 的默认实现__repr__通常无法实现此目标,因为它忽略了对开发人员有用的信息。

出于这个原因,如果我有一个足够简单的__str__,我通常只是尝试通过以下方式获得两全其美的东西:

def __repr__(self):
    return '{0} ({1})'.format(object.__repr__(self), str(self))
Run Code Online (Sandbox Code Playgroud)


zan*_*ngw 5

要记住的一件重要的事情是容器__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))"
Run Code Online (Sandbox Code Playgroud)

Python 更倾向于明确性而不是可读性, a__str__的调用tuple会调用所包含的对象' __repr__,即对象的“正式”表示。尽管正式表示比非正式表示更难阅读,但它是明确的并且对错误更稳健。


Ija*_*han 5

摘自Fluent Python一书:

Python对象的基本要求是提供其自身的可用字符串表示形式,一种用于调试和记录,另一种用于呈现给最终用户。这就是为什么
特殊方法__repr____str__存在于数据模型中的原因。


小智 5

简而言之:

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'
Run Code Online (Sandbox Code Playgroud)