Python中__str__和__repr_之间有什么区别?
当前回答
具有toString方法语言经验的程序员倾向于实现__str__而不是__repr_。如果只在Python中实现这些特殊方法之一,请选择__repr_。
来自Luciano Ramalho的《流利的Python》一书。
其他回答
您可以从以下代码中获得一些见解:
class Foo():
def __repr__(self):
return("repr")
def __str__(self):
return("str")
foo = Foo()
foo #repr
print(foo) #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.Ddecimal(“1.05”)的结果调用print()时,将打印原始数字;此输出为字符串形式,可以使用__str__()实现。如果我们简单地输入表达式,我们会得到一个decimal.decimal输出-这个输出是以表示形式的,可以用__repr_()实现。所有Python对象都有两种输出形式。字符串形式设计为人类可读。表示形式被设计为生成输出,如果将其提供给Python解释器,将(在可能的情况下)再现所表示的对象。
Python中__str__和__repr_之间有什么区别?
__str__(读作“dunder(双下划线)字符串”)和__repr_(读作”dunder repper“(代表“表示”))都是基于对象状态返回字符串的特殊方法。
__如果缺少__str__,repr_将提供备份行为。
因此,应该首先编写一个__repr_,允许您从它返回的字符串中重新实例化等效对象,例如使用eval或在Python shell中逐个字符地键入它。
在以后的任何时候,如果认为有必要,可以为实例的用户可读字符串表示编写__str__。
__字符串__
如果打印对象,或将其传递给format、str.format或str,则如果定义了__str__方法,则将调用该方法,否则将使用__repr_。
__代表__
__repr_方法由内置函数repr调用,当它计算返回对象的表达式时,它会在python外壳上响应。
由于它为__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__如何有用?
让我们看看使用Pythonshell和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 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__的后备方案,在编写__str__之前,应该编写一个__repr___,供开发人员在调试中使用。
只有当需要对象的文本表示时,才需要__str__。
结论
为您编写的对象定义__repr_,以便您和其他开发人员在开发时使用它时有一个可复制的示例。当需要可读字符串表示时,定义__str__。
除了给出的所有答案外,我想补充几点:-
1) 当您只需在交互式python控制台上写入对象名称并按enter键时,就会调用__repr_()。
2) __str__()在使用带有print语句的对象时被调用。
3) 在这种情况下,如果缺少__str__,那么print和任何使用str()的函数都会调用对象的__repr_()。
4) 容器的__str__(),当调用时将执行其包含元素的__repr_()方法。
5) 在__str__()内调用的str()可能会在没有基本情况的情况下递归,并且在最大递归深度上出错。
6) __repr_()可以调用repr(),它将尝试自动避免无限递归,用…替换已经表示的对象。。。。
简而言之,__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(对象)返回包含对象的可打印表示形式的字符串。这与转换产生的值相同(相反引号)。有时,作为一个普通的函数。对于许多类型,此函数会尝试返回一个字符串,当传递给eval(),否则表示形式是一个字符串包含对象类型名称的尖括号以及通常包括姓名和对象的地址。类可以控制此函数返回的内容为其实例定义__repr_()方法。
以下是str的文档:
str(对象=“”)返回一个字符串,该字符串包含可打印的对象的表示。对于字符串,这将返回字符串它本身与repr(object)的区别在于str(object)没有始终尝试返回eval()可接受的字符串;它的目标是返回一个可打印的字符串。如果未给定参数,则返回空字符串“”。
推荐文章
- Numpy Max vs amax vs maximum
- 我应该在.gitignore文件中添加Django迁移文件吗?
- 每n行有熊猫
- 实例属性attribute_name定义在__init__之外
- 如何获取在Python中捕获的异常的名称?
- 第一次出现的值大于现有值的Numpy
- 如何从Python函数中返回两个值?
- 前一个月的Python日期
- Python中方括号括起来的列表和圆括号括起来的列表有什么区别?
- Python日志记录不输出任何东西
- 每n秒运行特定代码
- SQLAlchemy是否有与Django的get_or_create等价的函数?
- 如何将python datetime转换为字符串,具有可读格式的日期?
- 美丽的汤和提取div及其内容的ID
- 在Python中重置生成器对象