__str__和__repr__有什么区别?

Python中#0#1有什么区别?

904774 次浏览

一个(非官方)Python参考Wiki(存档副本)到effbot:

__str__"计算对象的“非正式”字符串表示。这与#1的不同之处在于它不必是有效的Python表达式:可以使用更方便或更简洁的表示。"

#0:python对象的表示形式,通常ava会将其转换回该对象

#0:就是你认为是文本形式的对象

e. g.

>>> s="""w'o"w""">>> repr(s)'\'w\\\'o"w\''>>> str(s)'w\'o"w'>>> eval(str(s))==sTraceback (most recent call last):File "<stdin>", line 1, in <module>File "<string>", line 1w'o"w^SyntaxError: EOL while scanning single-quoted string>>> eval(repr(s))==sTrue

除非你特别采取行动来确保,否则大多数类都没有有用的结果:

>>> 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__(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__的输入的模糊无法实现的目标!

我的经验法则:__repr__是为开发人员准备的,__str__是为客户准备的。

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

首先,让我重申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,这样这样的代码就可以正常工作。这就是为什么会出现“val”的原因:如果你有足够的信息,所以eval(repr(c))==c,这意味着你知道关于c的所有信息。如果这足够容易,至少以模糊的方式,那就去做。如果不是,请确保你有足够的关于c的信息。我通常使用一种类似ava的格式:"MyClass(this=%r,that=%r)" % (self.this,self.that)。这并不意味着你真的可以构造MyClass,或者那些是正确的构造函数参数——但它是表达“这是你需要知道的关于这个实例的一切”的有用形式。

注意:我在上面使用了%r,而不是%s。您总是想在__repr__实现中使用repr()[或%r格式字符,等效地],或者您正在破坏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, helloworld, this is a list, oh I don't know, containing just 4 elements]

不是很明显。具体来说,容器中的字符串会发现它太容易扰乱它的字符串表示。面对歧义,请记住,Python抵制猜测的诱惑。如果您在打印列表时想要上述行为,只需

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

(你也可以弄清楚如何处理字典。

总结

为您实现的任何类实现__repr__。这应该是第二天性。如果您认为有一个在易读性方面出错的字符串版本会很有用,请实现__str__

老实说,eval(repr(obj))从来没有被使用过。如果你发现自己在使用它,你应该停止,因为eval很危险,字符串是一种非常低效的序列化对象的方式(用pickle代替)。

因此,我建议设置__repr__ = __str__。原因是str(list)在元素上调用repr(我认为这是Python 3没有解决的最大设计缺陷之一)。实际的repr可能不会像print([your, objects])的输出那样有很大帮助。

根据我的经验,为了限定这一点,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(双下划线)string”)和__repr__(读作“dunder-repper”(表示))都是基于对象状态返回字符串的特殊方法。

如果缺少__str__,则__repr__提供备份行为。

因此,应该首先编写一个__repr__,允许您从它返回的字符串中重新实例化等效对象,例如使用eval或在Python shell中以字符换字符的方式键入它。

在以后的任何时候,当认为有必要时,可以为实例的用户可读字符串表示编写__str__

__str__

如果您打印一个对象,或将其传递给formatstr.formatstr,那么如果定义了__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源代码)类似于:

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

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

<__main__.Foo object at 0x7f80665abdd0>

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

__repr__怎么可能有用?

让我们看看使用Python shell和datetime对象它有多有用。首先我们需要导入datetime模块:

import datetime

如果我们在shell中调用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源代码)的方式。它相当复杂,因为再现这样一个对象所需的所有属性:

def __repr__(self):"""Convert to formal string, for repr()."""L = [self._year, self._month, self._day,  # These are never zeroself._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__

>>> print(decimal.Decimal(23) / decimal.Decimal("1.05"))21.90476190476190476190476190>>> decimal.Decimal(23) / decimal.Decimal("1.05")Decimal('21.90476190476190476190476190')

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

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

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

def __repr__(self):return '{0} ({1})'.format(object.__repr__(self), str(self))

要记住的一件重要事情是容器的__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__,对象的“正式”表示。尽管正式表示比非正式表示更难阅读,但它是明确的,并且对错误更健壮。

简单地说:

__str__用于显示其他人对您的对象易于阅读的字符串表示。

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

假设我想创建一个Fraction类,其中分数的字符串表示为'(1/2)',对象(Fraction类)表示为'Fraction(1,2)'

所以我们可以创建一个简单的Fraction类:

class Fraction:def __init__(self, num, den):self.__num = numself.__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)

除了以上的答案外,我想补充几点:

1)__repr__()在交互式python控制台上写入对象的名称并按回车键时调用。

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

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

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

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

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

str-从给定的对象创建一个新的字符串对象。

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

差异:

str():

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

repr():处理方法

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

书名流利的Python

Python对象的基本要求是提供可用的自身的字符串表示,用于调试和日志记录,另一个用于向最终用户展示。这就是为什么
特殊方法__repr____str__存在于数据模型中。

在汉斯·彼得·朗坦根的书用于计算科学的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'

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

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

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

直观地理解__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

希望这能帮助你建立具体的基础来探索更多的答案。

简而言之:

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 logginglogger = logging.getLogger(logging.INFO)logger.info(demo) # use __str__, output 'str' to stdout
from pprint import pprint, pformatpprint(demo) # use __repr__, output 'repr' to stdoutresult = pformat(demo) # use __repr__, result is string which value is 'str'

__repr__在任何地方都使用,除了printstr方法(当定义了__str__时!)

  1. __str__必须返回字符串对象,而__repr__可以返回任何python表达式。
  2. 如果缺少__str__实现,则使用__repr__函数作为后备。如果缺少__repr__函数实现,则没有后备。
  3. 如果__repr__函数返回对象的String表示,我们可以跳过__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 strprint(str(ci2))  #C2 class strprint(repr(ci2)) #<__main__.C2 object at 0x0000024C44AE12E8>print(ci3)       #C3 class reprprint(str(ci3))  #C3 class reprprint(repr(ci3)) #C3 class reprprint(ci4)       #C4 class strprint(str(ci4))  #C4 class strprint(repr(ci4)) #C4 class repr

(2020年进入)

__str__()__repr__()有什么区别?

太长别读:str()/repr()和__str__()/__repr的区别__()

这个问题已经存在很长时间了,有各种各样的答案,其中大多数是正确的(更不用说几个Python社区的传说[!])。然而,当它归结到本质时,这个问题类似于问str()repr()内置函数之间的区别。我将用我自己的话描述差异(这意味着我可能是从核心Python编程中“借用”的,所以请原谅我)。

两者都有str()repr()有相同的基本工作:它们的目标是返回Python对象的字符串表示。字符串表示的善良是它们的区别。

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

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

>>> x, y = 'foo', 123>>> str(x), str(y)('foo', '123')

我们可以在这两种情况下都取什么是里面的报价并将它们逐字输入Python解释器吗?让我们试一试:

>>> 123123>>> fooTraceback (most recent call last):File "<stdin>", line 1, in <module>NameError: name 'foo' is not defined

显然,你可以为int,但不一定为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

所以这告诉你Python shell只是eval()你给它什么。明白了吗?现在,让我们repr()这两个表达式,看看我们得到了什么。更具体地说,获取它的输出并将这些转储到解释器中(稍后我们将讨论这一点):

>>> repr(x), repr(y)("'foo'", '123')>>> 123123>>> 'foo''foo'

哇,他们两者工作吗?那是因为'foo'虽然是该字符串的可打印字符串表示,但它没有可评估,但"'foo'"是。123是由str()repr()调用的有效Pythonint。当我们用这些调用eval()时会发生什么?

>>> eval('123')123>>> eval("'foo'")'foo'

它之所以有效,是因为123'foo'是有效的Python对象。另一个关键的收获是,虽然有时两者都返回相同的东西(相同的字符串表示形式),但并非总是如此。(是的,是的,我可以在eval()有效的地方创建一个变量foo,但这不是重点。)

更多关于两对的事实

  1. 有时,str()repr()被称为隐含,这意味着它们代表用户调用:当用户执行#2(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__()(每repr())。

每个对象都从所有对象创建的基类继承__repr__

class Person:pass
p=Person()

如果你调用repr(p),你会得到这个默认值:

 <__main__.Person object at 0x7fb2604f03a0>

但是如果你调用str(p),你会得到相同的输出。这是因为当__str__不存在时,Python调用__repr__

让我们实现自己的__str__

class Person:def __init__(self,name,age):self.name=nameself.age=agedef __repr__(self):print("__repr__ called")return f"Person(name='{self.name}',age={self.age})"
p=Person("ali",20)

print(p)str(p)将返回

 __repr__ calledPerson(name='ali',age=20)

让我们添加__str__()

class Person:def __init__(self, name, age):self.name = nameself.age = age        
def __repr__(self):print('__repr__ called')return f"Person(name='{self.name}, age=self.age')"    
def __str__(self):print('__str__ called')return self.name
p=Person("ali",20)

如果我们调用print(p)和str(p),它将调用__str__(),因此它将返回

__str__ calledali

repr(p)将返回

repr调用"Person(name='ali, age=self.age')"

让我们省略__repr__,只实现__str__

class Person:def __init__(self, name, age):self.name = nameself.age = age
def __str__(self):print('__str__ called')return self.name
p=Person('ali',20)

print(p)将查找__str__并返回:

__str__ calledali

如果我们定义了__repr____str__f'name is {p}'将调用__str__

你可以从这段代码中得到一些见解:

class Foo():def __repr__(self):return("repr")def __str__(self):return("str")
foo = Foo()foo #reprprint(foo) #str

具有toString方法语言经验的程序员倾向于实现__str__而不是__repr__。如果您只在Python中实现这些特殊方法之一,请选择__repr__

流利的Python书,拉马略,卢西亚诺。

基本上__str__str()用于创建人类可读的输出,必须面向最终用户。另一方面,repr()__repr__主要返回对象的规范字符串表示,用于调试和开发,帮助程序员。

repr()在我们调试或日志时使用。另一方面str()user用于非开发人员,如(QA)或user。

class Customer:def __init__(self,name):self.name = namedef __repr__(self):return "Customer('{}')".format(self.name)def __str__(self):return f"cunstomer name is {self.name}"
cus_1 = Customer("Thusi")print(repr(cus_1)) #print(cus_1.__repr__())print(str(cus_1)) #print(cus_1.__str__())

在我看来:

__str__用于将对象转换为字符串,这使得对象更具可读性(对于像我这样的客户)。然而,__repr__必须用于将类的对象表示为字符串,这似乎更明确。所以__repr__最有可能被开发人员用于开发和调试。