官方Python文档和Python增强提案索引似乎都没有明确规定如何覆盖这些方法的清晰指南,除了3.3特殊方法名称之外,其中之一是关于__repr__()
的:
如果可能的话,这应该看起来像一个有效的Python表达式,可以用来重新创建具有相同值的对象[...] 这通常用于调试,因此表示形式必须富含信息且不含歧义。
我喜欢从一些标准库模块中实现__repr__()
的方式中获得灵感,例如socket.socket
:
$ python3
>>> from socket import socket
>>> socket()
<socket.socket fd=3, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('0.0.0.0', 0)>
所以这里的模式是。虽然__repr__()更适合于调试/测试目的,但__str__()的范围更加非正式,我推断甚至可以使用更松散的规则。请注意,如果重写了__repr__()但没有重写__str__(),__repr__()将调用__str__()。在这里,如果我必须选择一些规则,我更喜欢让__str__()类似于__repr__(),但进行修改:显示的项目数量。我不需要像__repr__那样冗长。显示的值类型。我包括最“重要”的值,甚至包括不反映最初传递给__init__()的参数的值。
我正在开发的一款PDF库中有几个例子。其中包括两个类PdfFileReader
和PdfFileWriter
,它们的__repr__()
和__str__()
方法输出如下:
r = PdfFileReader("samplecode/pdfsamples/jpeg.pdf")
w = PdfFileWriter()
print(r)
print(str(r))
print(repr(r))
print(w)
print(str(w))
print(repr(w))
$ python3 repr.py
<pypdf.pdf.PdfFileReader _filepath=samplecode/pdfsamples/jpeg.pdf, stream=<_io.BytesIO object at 0x7eff60f07e60>, strict=True, debug=False>
<pypdf.pdf.PdfFileReader _filepath=samplecode/pdfsamples/jpeg.pdf, stream=<_io.BytesIO object at 0x7eff60f07e60>, strict=True, debug=False>
<pypdf.pdf.PdfFileReader _filepath=samplecode/pdfsamples/jpeg.pdf, stream=<_io.BytesIO object at 0x7eff60f07e60>, strict=True, debug=False>
<pypdf.pdf.PdfFileWriter _header=%PDF-1.3, debug=False>
<pypdf.pdf.PdfFileWriter _header=%PDF-1.3, debug=False>
<pypdf.pdf.PdfFileWriter _header=%PDF-1.3, debug=False>
请参阅 2. 内置函数 以了解 repr()
:
对于许多类型,此函数尝试返回一个字符串,该字符串在传递给 eval() 时将生成一个具有相同值的对象,否则表示是一个带有角括号的字符串,其中包含对象类型的名称以及通常包括对象的名称和地址的其他信息。 [...]
str
和repr
返回两个不同的字符串真的有必要吗? - Mark Ransom__str__ = __repr__
(或反之亦然)以复制实现。 - jasonharper