Let’s take a couple of fictional classes as an example:
import requests
class A:
def __init __ (self, a = "string", b = 10, c = ["a", "b", "c", 1, 2, 3]):
# parameter c - arbitrary length
self.a = a
self.b = b
self.c = c
class B:
def __init __ (self, A_object):
# A_object is an object of type A
self.neighbor = A_object
self.session = requests.Session ()
1) How should I write __repr__
and __str__
for these classes?
2) Documentation says that __ repr__
is an unambiguous string representation of an object that can be used to recreate the exact same object, and if that is not possible, then output some useful message . It is very likely that you want to serialize the object this way. What, then, is the difference from the bundle __getstate__
, __setstate__
? These two methods can also easily return a string, and the requirements for this string are the same – an unambiguous representation of an object. Why duplication?
Conversely, as a replacement for getstate, setstate, you can think of the following:
def __repr __ (self):
return "A ({a}, {b}, {c})". format (a = self.a, b = self.b, c = self.c)
and then call this:
A1 = A ()
A2 = eval (A1 .__ repr __ ())
3) The same documentation says that __str__
should output a nice, readable informational message that reflects the object. How then can you tell the difference between the result of this method and some useful message from __repr__
?
4) It is not always possible to represent an object as a string. For example, functions, long collections, other objects without str and without repr. It turns out that in this case either the __repr__
requirement is not met, or it is necessary to display the contents of __dict__
for all such objects, which stores the value of all methods and variables. This solution looks bad, what should I do?
5) Returning to the documentation __repr__
– can you give an example of a situation where it is impossible to unambiguously represent an object as a string? Objects have nothing to do with the quantum world – they are ALWAYS deterministic, there is always a set of variables and a set of methods. but not in vain is this line in the documentation?
6) And then there is __format__
, which should also return a string …
Answer 1, authority 100%
datetime.date
illustrates the difference well:
& gt; & gt; & gt; from datetime import date
& gt; & gt; & gt; date.today () # sys.displayhook () uses repr () by default
datetime.date (2016, 6, 13)
& gt; & gt; & gt; print (date.today ()) # print uses str () here
2016-06-13
repr (obj)
returns a unambiguous text representation of an object useful for debugging, error messages, REPL, which (sometimes) allows it (theoretically) to be restored: eval (repr (obj)) == obj
.
str (obj)
returns readable text. For many objects, it makes sense to define __repr __ ()
(since the default implementation in object .__ repr__
is not very informative). It makes sense to define __str __ ()
for objects for which there is a “natural” human-readable (non-Python-specific) representation (as in the date example), for example, for logs.
If __str__
is not defined, then str ()
uses repr ()
.
Different formats are designed for different users (human / program, Python / general purpose). Here’s a graph to illustrate when different formats are useful:
^ ^
| | More human friendly
| + --- +
| | str |
| + --- +
|
| + ---- + + ---- +
| | repr | | json |
| + ---- + + ---- +
|
| + ------ +
| | pickle |
| + ------ +
|
| | Machine readable
+ --------------------------------- & gt;
Python specific - & gt; More general
1) How should I write
__repr__
and__str__
for these classes?
class A:
def __repr __ (self):
return "A (% r,% r,% r)"% (self.a, self.b, self.c)
class B:
def __repr __ (self):
return "& lt; B (neighbor =% r), session =% r & gt;" % (self.neighbor, self.session)
B
objects cannot be restored from repr ()
.
2) The documentation says that
__repr__
is an unambiguous representation of an object in the form of a string, which can be used to recreate the exact same object, and if this is not possible, then output some useful message. It is very likely that you want to serialize the object this way. What, then, is the difference from the bundle__getstate__
,__setstate__
? These two methods can also easily return a string, and the requirements for this string are the same – an unambiguous representation of an object. Why duplicate?
pickle
(__getstate __ / __ setstate__
) is not a human readable format. Design goals and constraints are different. Just because eval (repr (obj))
sometimes works doesn’t mean it’s a good idea to use it instead of pickle.loads (pickle.dumps (obj))
or json.loads (json.dumps (obj))
.
The main consumer of repr ()
is a human. The pickle.dumps ()
consumer is typically a program, for example multiprocessing
uses pickle
to exchange data between processes.
3) The same documentation says that
__str__
should output a nice, readable informational message that reflects the object. How then can you tell the difference between the result of this method and some useful message from__repr__
?
If you don’t see the type name, then it’s not __repr __ ()
(with the obvious exception of constants (Python literals) such as 'abc'
, 123
).
4) It is not always possible to represent an object as a string. For example, functions, long collections, other objects without str and without repr. It turns out that in this case either the
__repr__
requirement is not met, or it is necessary to display the contents of__dict__
for all such objects, which stores the value of all methods and variables. This solution looks bad, what should I do?
eval (repr (obj))
is a hint, not a requirement: if the object is large, then obviously you need to shorten its representation. In many cases, you can use ellipsis:
& gt; & gt; & gt; numpy.arange (10000000)
array ([0, 1, 2, ..., 9999997, 9999998, 9999999])
& gt; & gt; & gt; print (numpy.arange (10000000))
[0 1 2 ..., 9999997 9999998 9999999]
Again: the consumer repr ()
is the Python programmer who sees this view in the REPL or debugger.
5) Returning to the documentation
__repr__
– can you give an example of a situation where it is impossible to unambiguously represent an object as a string? Objects have nothing to do with the quantum world – they are ALWAYS deterministic, there is always a set of variables and a set of methods. but not in vain is this line in the documentation?
The documentation talks about the case where eval (repr (obj)) == obj
doesn’t make sense:
& gt; & gt; & gt; object ()
& lt; object object at 0x7f9ff2c8c1d0 & gt;
6) And then there is
__format__
, which should also return a string …
This special method allows a type to override how format ()
behaves, for example:
& gt; & gt; & gt; "{:% Y-% m-% d}". Format (datetime.today ())
'2016-06-13'
Python 2 has __unicode __ ()
as __str __ ()
, but unicode
returns. Also __fspath __ ()
(PEP 519) appeared. There may be other protocols that return strings (with their own rationale).