Python中__str__和__repr_之间有什么区别?
当前回答
摘自《流利的Python》一书:
Python对象的基本要求是提供可用的自身的字符串表示,用于调试和日志记录,另一个用于向最终用户演示。这就是为什么数据模型中存在特殊的方法repr_和str__。
其他回答
需要记住的一点是,容器的__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__调用调用所包含对象的__repr_,即对象的“形式”表示。虽然正式表示比非正式表示更难理解,但它是明确的,并且对bug更为健壮。
来自effbot的(非官方)Python参考Wiki(存档副本):
__str__“计算对象的“非正式”字符串表示。这与__repr_不同,因为它不必是有效的Python表达式:可以使用更方便或更简洁的表示。”
(2020条目)
Q: __str__()和__repr___()之间有什么区别?
TL;博士:
LONG
这个问题已经存在了很长一段时间,有很多答案都是正确的(更不用说来自几个Python社区的传说[!])。然而,当谈到本质时,这个问题类似于询问str()和repr()内置函数之间的区别。我将用我自己的语言描述这些差异(这意味着我可能是在“借用”核心Python编程,所以请原谅我)。
str()和repr()都有相同的基本任务:它们的目标是返回Python对象的字符串表示。什么样的字符串表示是它们的区别。
str()和__str__()返回可打印的字符串表示形式对象。。。人类可读/供人类食用的东西repr()&__repr_()返回一个对象的字符串表示,该对象是一个有效的Python表达式,您可以传递给eval()或在Python shell中键入,而不会出现错误。
例如,让我们将一个字符串分配给x,将一个int分配给y,并简单地显示每个字符串的可读字符串版本:
>>> x, y = 'foo', 123
>>> str(x), str(y)
('foo', '123')
我们可以在这两种情况下获取引号中的内容并将其逐字输入Python解释器吗?让我们试一试:
>>> 123
123
>>> foo
Traceback (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')
>>> 123
123
>>> 'foo'
'foo'
哇,他们都工作了?这是因为“foo”虽然是该字符串的可打印字符串表示,但它不是可求值的,但“'fo'”是.123是str()或repr()调用的有效Python int。当我们用这些调用eval()时会发生什么?
>>> eval('123')
123
>>> eval("'foo'")
'foo'
它之所以有效,是因为123和“foo”是有效的Python对象。另一个关键点是,虽然有时两者都返回相同的东西(相同的字符串表示),但情况并非总是如此。(是的,是的,我可以在eval()工作的地方创建一个变量foo,但这不是重点。)
关于这两对的更多事实
有时,str()和repr()是隐式调用的,这意味着它们是代表用户调用的:当用户执行print(Py1/Py2)或调用print()(Py3+)时,即使用户没有显式调用str((),也会在显示对象之前代表用户进行这样的调用。在Pythonshell(交互式解释器)中,如果在>>提示符下输入变量并按RETURN,解释器将显示对该对象隐式调用repr()的结果。要将str()和repr()连接到__str__()和__repr___(),请认识到对内置函数(即str(x)或repr(y))的调用会导致调用其对象的相应特殊方法:x.__str____通过为Python类实现__str__()和__repr_(),可以重载内置函数(str()和repr()),允许将类的实例传递给str(()和repr()。当进行此类调用时,它们会返回并调用类'__str__()和__repr___()(根据#3)。
>>> 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解释器,将(在可能的情况下)再现所表示的对象。
每个对象都从所有对象创建的基类继承__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=name
self.age=age
def __repr__(self):
print("__repr__ called")
return f"Person(name='{self.name}',age={self.age})"
p=Person("ali",20)
print(p)和str(p)将返回
__repr__ called
Person(name='ali',age=20)
让我们添加__str__()
class Person:
def __init__(self, name, age):
self.name = name
self.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__ called
ali
repr(p)将返回
repr调用“人(name=‘ali,age=self.age’)”
让我们省略__repr_,只实现__str__。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
print('__str__ called')
return self.name
p=Person('ali',20)
print(p)将查找__str__并返回:
__str__ called
ali
注意:如果我们定义了__repr_和__str__,则f'name为{p}'将调用__str__
推荐文章
- 如何用OpenCV2.0和Python2.6调整图像大小
- 在每个列表元素上调用int()函数?
- 当使用代码存储库时,如何引用资源的相对路径
- 如何在Flask-SQLAlchemy中按id删除记录
- 在Python中插入列表的第一个位置
- Python Pandas只合并某些列
- 如何在一行中连接两个集而不使用“|”
- 从字符串中移除前缀
- 代码结束时发出警报
- 如何在Python中按字母顺序排序字符串中的字母
- 在matplotlib中将y轴标签添加到次要y轴
- 如何消除数独方块的凹凸缺陷?
- 为什么出现这个UnboundLocalError(闭包)?
- 使用Python请求的异步请求
- 如何检查一个对象是否是python中的生成器对象?