__repr__ 在 Python 中有什么区别？
Alex summarized well but, surprisingly, was too succinct.
First, let me reiterate the main points in Alex’s post:
- The default implementation is useless (it’s hard to think of one which wouldn’t be, but yeah)
__repr__goal is to be unambiguous
__str__goal is to be readable
__str__uses contained objects’
Default implementation is useless
This is mostly a surprise because Python’s defaults tend to be fairly useful. However, in this case, having a default for
__repr__ which would act like:
return "%s(%r)" % (self.__class__, self.__dict__)
would have been too dangerous (for example, too easy to get into infinite recursion if objects reference each other). So Python cops out. Note that there is one default which is true: if
__repr__ is defined, and
__str__ is not, the object will behave as though
This means, in simple terms: almost every object you implement should have a functional
__repr__ that’s usable for understanding the object. Implementing
__str__ is optional: do that if you need a “pretty print” functionality (for example, used by a report generator).
The goal of
__repr__ is to be unambiguous
Let me come right out and say it — I do not believe in debuggers. I don’t really know how to use any debugger, and have never used one seriously. Furthermore, I believe that the big fault in debuggers is their basic nature — most failures I debug happened a long long time ago, in a galaxy far far away. This means that I do believe, with religious fervor, in logging. Logging is the lifeblood of any decent fire-and-forget server system. Python makes it easy to log: with maybe some project specific wrappers, all you need is a
log(INFO, "I am in the weird function and a is", a, "and b is", b, "but I got a null C — using default", default_c)
But you have to do the last step — make sure every object you implement has a useful repr, so code like that can just work. This is why the “eval” thing comes up: if you have enough information so
eval(repr(c))==c, that means you know everything there is to know about
c. If that’s easy enough, at least in a fuzzy way, do it. If not, make sure you have enough information about
c anyway. I usually use an eval-like format:
"MyClass(this=%r,that=%r)" % (self.this,self.that). It does not mean that you can actually construct MyClass, or that those are the right constructor arguments — but it is a useful form to express “this is everything you need to know about this instance”.
Note: I used
%r above, not
%s. You always want to use
%r formatting character, equivalently] inside
__repr__ implementation, or you’re defeating the goal of repr. You want to be able to differentiate
The goal of
__str__ is to be readable
Specifically, it is not intended to be unambiguous — notice that
str(3)==str("3"). Likewise, if you implement an IP abstraction, having the str of it look like 192.168.1.1 is just fine. When implementing a date/time abstraction, the str can be "2010/4/12 15:35:22", etc. The goal is to represent it in a way that a user, not a programmer, would want to read it. Chop off useless digits, pretend to be some other class — as long is it supports readability, it is an improvement.
__str__ uses contained objects’
This seems surprising, doesn’t it? It is a little, but how readable would it be if it used their
[moshe is, 3, hello world, this is a list, oh I don't know, containing just 4 elements]
Not very. Specifically, the strings in a container would find it way too easy to disturb its string representation. In the face of ambiguity, remember, Python resists the temptation to guess. If you want the above behavior when you’re printing a list, just
print "[" + ", ".join(l) + "]"
(you can probably also figure out what to do about dictionaries.
__repr__ for any class you implement. This should be second nature. Implement
__str__ if you think it would be useful to have a string version which errs on the side of readability.
__repr__: representation of python object usually eval will convert it back to that object
__str__: is whatever you think is that object in text form
>>> s="""w'o"w""" >>> repr(s) '\'w\\\'o"w\'' >>> str(s) 'w\'o"w' >>> eval(str(s))==s Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<string>", line 1 w'o"w ^ SyntaxError: EOL while scanning single-quoted string >>> eval(repr(s))==s True
In short, the goal of
__repr__is to be unambiguous and
__str__is to be readable.
Here is a good example:
>>> import datetime >>> today = datetime.datetime.now() >>> str(today) '2012-03-14 09:21:58.130922' >>> repr(today) 'datetime.datetime(2012, 3, 14, 9, 21, 58, 130922)'
Read this documentation for repr:
Return a string containing a printable representation of an object. This is the same value yielded by conversions (reverse quotes). It is sometimes useful to be able to access this operation as an ordinary function. 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. A class can control what this function returns for its instances by defining a
Here is the documentation for str:
Return a string containing a nicely printable representation of an object. For strings, this returns the string itself. The difference with
str(object)does not always attempt to return a string that is acceptable to
eval(); its goal is to return a printable string. If no argument is given, returns the empty string,
Apart from all the answers given, I would like to add few points :-
__repr__() is invoked when you simply write object's name on interactive python console and press enter.
__str__() is invoked when you use object with print statement.
3) In case, if
__str__ is missing, then print and any function using
__repr__() of object.
__str__() of containers, when invoked will execute
__repr__() method of its contained elements.
str() called within
__str__() could potentially recurse without a base case, and error on maximum recursion depth.
__repr__() can call
repr() which will attempt to avoid infinite recursion automatically, replacing an already represented object with
On page 358 of the book Python scripting for computational science by Hans Petter Langtangen, it clearly states that
__repr__aims at a complete string representation of the object;
__str__is to return a nice string for printing.
So, I prefer to understand them as
- repr = reproduce
- str = string (representation)
from the user's point of view although this is a misunderstanding I made when learning python.
A small but good example is also given on the same page as follows:
In : str('s') Out: 's'
In : repr(‘s’)
In : eval(str(‘s’))
Traceback (most recent call last):
File “<ipython-input-40-abd46c0c43e7>”, line 1, in <module>
File “<string>”, line 1, in <module>
NameError: name ‘s’ is not defined
In : eval(repr(‘s’))
To put it simply:
__str__ is used in to show a string representation of your object to be read easily by others.
__repr__ is used to show a string representation of the object.
Let's say I want to create a
Fraction class where the string representation of a fraction is '(1/2)' and the object (Fraction class) is to be represented as 'Fraction (1,2)'
So we can create a simple Fraction class:
class Fraction: def __init__(self, num, den): self.__num = num self.__den = den
def __str__(self): return '(' + str(self.__num) + '/' + str(self.__den) + ')' def __repr__(self): return 'Fraction (' + str(self.__num) + ',' + str(self.__den) + ')'
f = Fraction(1,2)
print('I want to represent the Fraction STRING as ’ + str(f)) # (1/2)
print('I want to represent the Fraction OBJECT as ', repr(f)) # Fraction (1,2)
str - Creates a new string object from the given object.
repr - Returns the canonical string representation of the object.
- makes object readable
- generates output for end-user
- needs code that reproduces object
- generates output for developer
You can get some insight from this code:
class Foo(): def __repr__(self): return("repr") def __str__(self): return("str")
foo = Foo()
One important thing to keep in mind is that container's
__str__uses contained objects'
>>> 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 favors unambiguity over readability, the
__str__ call of a
tuple calls the contained objects'
__repr__, the "formal" representation of an object. Although the formal representation is harder to read than an informal one, it is unambiguous and more robust against bugs.