__str__ vs. __repr__

Tim Peters tim_one at email.msn.com
Sat Nov 6 10:02:47 CET 1999


[Tim]
>> repr(obj) should return a string such that
>>     eval(repr(obj)) == obj

[Donn Cave]
> For real?

This, along with the later claim about what str() "should do", are
paraphrased from the Language Reference Manual (3.3.1 Basic customization).
It's "why" e.g. the equation above holds for repr(string) but not for
str(string).  The builtin types took this stuff as seriously as they could,
modulo some unfortunate lapses (like repr(float)) covered elsewhere in this
thread.

>  I'm very used to seeing repr's that don't eval at all -
>
> '<socket object, fd=3, family=2, type=1, protocol=0>'
> "<open file '<stdout>', mode 'w' at 80005660>"
> '<exceptions.NameError instance at 80048ae0>'

Are you for real <0.9 wink>?  Be reasonable.

> ...
> Well, really I guess I would prefer that authors _not_ try to capture
> *everything* important, if that means a large data dump.  repr is used
> in lots of places, like the interactive interpreter, where the output
> only has to be roughly indicative,

The latter is str()'s purpose (see 3.3.1 again), and the thread was arguing
(among other things) that the interpreter use it (instead of repr())
interactively.

> and I have never seen and can't find any example of its use with
> eval or in any context where it has to be definitive.

I've seen it used often as a poor-man's pickle, and as a way to email Python
objects as plain text.  repr() is very useful for that.  Unfortunately, most
class authors seem to ignore the distinction (my classes don't!), and that
limits its usefulness.  The lapses in the core also hurt.  One email
response I didn't see posted here describes a typical example of the latter:

<ANONYMOUS>

I've only been writing Python for a year or so, but bumped into this 'cheat'
and had to write floats out to a file using binary format, a portability
nightmare.  The floats were in an array, and you can't pickle arrays.

>>> repr(12345678901234567.0)
'1.23456789012e+016'  # Just 12 digits!

is currently what you get.

>>> x = 12345678901234567.0
>>> x == eval(repr(x))  # Nope.
0

It sure would be nice to be able to count on
    eval(repr(obj)) == obj.

On the other hand, while repr(1L) has to return '1L',  there's no reason
str(1L) shouldn't be '1'.

</ANONYMOUS>

OTOH,

>>> x == eval("%24.16e" % x)
1
>>>

on any IEEE-754 conforming platform, as was covered in detail earlier.
That's what repr(float) should do.

> If there are folks who want to provide this functionality at the expense
> of making a string that's unusable for repr's normal applications,
> they should put it in a different function.

The language took its stand on this issue in 1991 <wink>, and you're arguing
against *that*.  I'm arguing for the language to finish what it started.

> ...
> Bah.  If we get str() because it's pleasant to read, aren't we worried
> that repr() will be harsh and stressful?  Will one repr() too many send
> one of us into a homicidal rage one of these days?

I said before that repr() is rarely appropriate -- but essential when it is.

> Let us think about taming the cruel repr()!  If I may speculate on what
> you're trying to say, str() is pleasant because it shows the data in
> form that has been digested for human consumption.  In contrast to
> repr(), which is intended for the machine.

Ah -- you *have* read section 3.3.1 <wink>.

> ...
> So look at the way it's really used.

Inconsistently, confusingly, and inappropriately, in both classes and (but
substantially less so) in the core types.  We can't deduce anything useful
about what should happen now based on what is a mess in practice.  My aim is
to get the mess cleaned up.

and-thanks-for-your-support<wink>-ly y'rs  - tim






More information about the Python-list mailing list