As the Python 2 documentation on __repr__
states:
If at all possible, this (i.e.
__repr__
) should look like a valid Python expression that could be used to recreate an object with the same value (given an appropriate environment).
So how come builtin __repr__
for classes does not act accordingly to that guideline?
>>> class A(object):
... pass
>>> repr(A)
"<class 'A'>"
To meet the guideline, the default __repr__
should return "A"
, i.e. generally A.__name__
. Why is it acting differently? It would be extra-easy to implement, I believe.
I can see in the answers that it is not clear in the discussion what repr
should return. The way I see it, the repr
function should return a string that allows you to reproduce the object:
Ad.1. Take a look at a built-in class case (taken from this SO question):
>>> from datetime import date
>>>
>>> repr(date.today()) # calls date.today().__repr__()
'datetime.date(2009, 1, 16)'
Apparently, the assumed context is as if you use the basic form of import, i.e. import datetime
, because if you would try eval(repr(date.today()))
, datetime
would not be recognized. So the point is that __repr__
doesn't need to represent the object from scratch. It's enough if it is unambiguous in a context the community agreed upon, e.g. using direct module's types and functions. Sounds reasonable, right?
Ad.2. Giving an impression of how the object could be reconstructed is not enough for repr
, I believe. Helpfulness in debugging is the purpose of str
.
So what I expect from repr
is allowing me to do eval
on the result. And in the case of a class, I would not like to get the whole code that would reconstruct the class from scratch. Instead, I would like to have an unambiguous reference to a class visible in my scope. The "Module.Class"
would suffice. No offence, Python, but "<class 'Module.Class'>"
doesn't just cut it.
Consider a slightly more complicated class:
class B(object):
def __init__(self):
self.foo=3
repr
would need to return something like
type("B", (object,), { "__init__": lambda self: setattr(self, "foo", 3) })
Notice one difficulty already: not all functions defined by the def
statement can be translated into a single lambda
expression. Change B
slightly:
class B(object):
def __init__(self, x=2, y, **kwargs):
print "in B.__init__"
How do you write an expression that defines B.__init__
? You can't use
lambda self: print "in B.__init__"
because lambda
expressions cannot contain statements. For this simple class, it is already impossible to write a single expression that defines the class completely.
Because the default __repr__
cannot know what statements were used to create the class.
The documentation you quote starts with If at all possible. Since it is not possible to represent custom classes in a way that lets you recreate them, a different format is used, which follows the default for all things not easily recreated.
If repr(A)
were to just return 'A'
, that'd be meaningless. You are not recreating A
, you'd just be referencing it then. "type('A', (object,), {})"
would be closer to reflecting the class constructor, but that'd be a) confusing for people not familiar with the fact python classes are instances of type
and b) never able to reflect methods and attributes accurately.
Compare the output to that of repr(type)
or repr(int)
instead, these follow the same pattern.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With