Neither the official Python documentation nor the Index of Python Enhancement Proposal seem to specify clear guidelines on how to override these methods, except for the 3.3 Special method names which, among other things, says of __repr__()
:
If at all possible, this should look like a valid Python expression
that could be used to recreate an object with the same value [...]
This is typically used for debugging, so it is important that the
representation is information-rich and unambiguous.
I like to take inspiration from how __repr__()
is implemented in some of the standard library modules, take e.g. 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)>
So the pattern here is <self.__class__.__module__ + "." + self.__class__.__name__ attribute1=value1, ..., attributeN=valueN>
.
While __repr__()
is preferred for debug/testing purposes, the scope of __str__()
is much more informal and I'd deduce that even looser rules apply. Note that if __repr__()
is overridden but __str__()
is not, __repr__()
calls __str__()
.
Here again, if I have to pick some rules I prefer to have __str__()
resemble __repr__()
, but modifying:
- The number of items displayed. I don't need to be verbose as
__repr__
mandates.
- The type of values displayed. I include the most "important" ones, and even values that do not reflect the arguments initially passed to
__init__()
.
Another few examples come from a PDF library I've been working on. There are two PdfFileReader
and PdfFileWriter
classes, and their __repr__()
and __str__()
methods have the following output:
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>
See also 2. Built-in Functions for repr()
:
[...] For many types, this function makes an attempt to return a string that
would yield an object with the same value when passed to eval(),
otherwise the representation is a string enclosed in angle brackets
that contains the name of the type of the object together with
additional information often including the name and address of the
object. [...]