2008-05-29 17:03:57 -04:00
|
|
|
PEP: 3140
|
|
|
|
Title: str(container) should call str(item), not repr(item)
|
|
|
|
Version: $Revision$
|
2008-06-03 11:35:18 -04:00
|
|
|
Last-Modified: $Date$
|
2015-09-15 08:32:16 -04:00
|
|
|
Author: Oleg Broytman <phd@phdru.name>,
|
2017-02-02 12:58:49 -05:00
|
|
|
Jim J. Jewett <jimjjewett@gmail.com>
|
2008-05-29 17:03:57 -04:00
|
|
|
Discussions-To: python-3000@python.org
|
|
|
|
Status: Rejected
|
|
|
|
Type: Standards Track
|
2017-02-02 12:58:49 -05:00
|
|
|
Content-Type: text/x-rst
|
2008-05-29 17:03:57 -04:00
|
|
|
Created: 27-May-2008
|
|
|
|
Post-History: 28-May-2008
|
|
|
|
|
|
|
|
|
|
|
|
Rejection
|
2017-02-02 12:58:49 -05:00
|
|
|
=========
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
Guido said this would cause too much disturbance too close to beta. See [1]_.
|
2008-05-29 17:03:57 -04:00
|
|
|
|
|
|
|
|
|
|
|
Abstract
|
2017-02-02 12:58:49 -05:00
|
|
|
========
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
This document discusses the advantages and disadvantages of the
|
|
|
|
current implementation of ``str(container)``. It also discusses the
|
|
|
|
pros and cons of a different approach - to call ``str(item)`` instead
|
|
|
|
of ``repr(item)``.
|
2008-05-29 17:03:57 -04:00
|
|
|
|
|
|
|
|
|
|
|
Motivation
|
2017-02-02 12:58:49 -05:00
|
|
|
==========
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
Currently ``str(container)`` calls ``repr`` on items. Arguments for it:
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
* containers refuse to guess what the user wants to see on
|
|
|
|
``str(container)`` - surroundings, delimiters, and so on;
|
|
|
|
* ``repr(item)`` usually displays type information - apostrophes
|
|
|
|
around strings, class names, etc.
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
Arguments against:
|
|
|
|
|
|
|
|
* it's illogical; ``str()`` is expected to call ``__str__`` if it exists,
|
|
|
|
not ``__repr__``;
|
|
|
|
* there is no standard way to print a container's content calling
|
|
|
|
items' ``__str__``, that's inconvenient in cases where ``__str__`` and
|
|
|
|
``__repr__`` return different results;
|
|
|
|
* ``repr(item)`` sometimes do wrong things (hex-escapes non-ASCII strings,
|
|
|
|
e.g.)
|
|
|
|
|
|
|
|
This PEP proposes to change how ``str(container)`` works. It is
|
|
|
|
proposed to mimic how ``repr(container)`` works except one detail - call
|
|
|
|
``str`` on items instead of ``repr``. This allows a user to choose
|
|
|
|
what results she want to get - from ``item.__repr__`` or ``item.__str__``.
|
2008-05-29 17:03:57 -04:00
|
|
|
|
|
|
|
|
|
|
|
Current situation
|
2017-02-02 12:58:49 -05:00
|
|
|
=================
|
|
|
|
|
|
|
|
Most container types (tuples, lists, dicts, sets, etc.) do not
|
|
|
|
implement ``__str__`` method, so ``str(container)`` calls
|
|
|
|
``container.__repr__``, and ``container.__repr__``, once called, forgets
|
|
|
|
it is called from ``str`` and always calls ``repr`` on the container's
|
|
|
|
items.
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
This behaviour has advantages and disadvantages. One advantage is
|
|
|
|
that most items are represented with type information - strings
|
|
|
|
are surrounded by apostrophes, instances may have both class name
|
|
|
|
and instance data::
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
>>> print([42, '42'])
|
|
|
|
[42, '42']
|
|
|
|
>>> print([Decimal('42'), datetime.now()])
|
|
|
|
[Decimal("42"), datetime.datetime(2008, 5, 27, 19, 57, 43, 485028)]
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
The disadvantage is that ``__repr__`` often returns technical data
|
|
|
|
(like '``<object at address>``') or unreadable string (hex-encoded
|
|
|
|
string if the input is non-ASCII string)::
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
>>> print(['тест'])
|
|
|
|
['\xd4\xc5\xd3\xd4']
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
One of the motivations for PEP 3138 is that neither ``repr`` nor ``str``
|
|
|
|
will allow the sensible printing of dicts whose keys are non-ASCII
|
|
|
|
text strings. Now that Unicode identifiers are allowed, it
|
|
|
|
includes Python's own attribute dicts. This also includes JSON
|
|
|
|
serialization (and caused some hoops for the json lib).
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
PEP 3138 proposes to fix this by breaking the "repr is safe ASCII"
|
|
|
|
invariant, and changing the way ``repr`` (which is used for
|
|
|
|
persistence) outputs some objects, with system-dependent failures.
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
Changing how ``str(container)`` works would allow easy debugging in
|
|
|
|
the normal case, and retain the safety of ASCII-only for the
|
|
|
|
machine-readable case. The only downside is that ``str(x)`` and
|
|
|
|
``repr(x)`` would more often be different -- but only in those cases
|
|
|
|
where the current almost-the-same version is insufficient.
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
It also seems illogical that ``str(container)`` calls ``repr`` on items
|
|
|
|
instead of ``str``. It's only logical to expect following code::
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
class Test:
|
|
|
|
def __str__(self):
|
|
|
|
return "STR"
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
def __repr__(self):
|
|
|
|
return "REPR"
|
2008-05-29 17:03:57 -04:00
|
|
|
|
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
test = Test()
|
|
|
|
print(test)
|
|
|
|
print(repr(test))
|
|
|
|
print([test])
|
|
|
|
print(str([test]))
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
to print::
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
STR
|
|
|
|
REPR
|
|
|
|
[STR]
|
|
|
|
[STR]
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
where it actually prints::
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
STR
|
|
|
|
REPR
|
|
|
|
[REPR]
|
|
|
|
[REPR]
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
Especially it is illogical to see that print in Python 2 uses ``str``
|
|
|
|
if it is called on what seems to be a tuple::
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
>>> print Decimal('42'), datetime.now()
|
|
|
|
42 2008-05-27 20:16:22.534285
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
where on an actual tuple it prints::
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
>>> print((Decimal('42'), datetime.now()))
|
|
|
|
(Decimal("42"), datetime.datetime(2008, 5, 27, 20, 16, 27, 937911))
|
2008-05-29 17:03:57 -04:00
|
|
|
|
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
A different approach - call ``str(item)``
|
|
|
|
=========================================
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
For example, with numbers it is often only the value that people
|
|
|
|
care about.
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
::
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
>>> print Decimal('3')
|
|
|
|
3
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
But putting the value in a list forces users to read the type
|
|
|
|
information, exactly as if ``repr`` had been called for the benefit of
|
|
|
|
a machine::
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
>>> print [Decimal('3')]
|
|
|
|
[Decimal("3")]
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
After this change, the type information would not clutter the ``str``
|
|
|
|
output::
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
>>> print "%s".format([Decimal('3')])
|
|
|
|
[3]
|
|
|
|
>>> str([Decimal('3')]) # ==
|
|
|
|
[3]
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
But it would still be available if desired::
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
>>> print "%r".format([Decimal('3')])
|
|
|
|
[Decimal('3')]
|
|
|
|
>>> repr([Decimal('3')]) # ==
|
|
|
|
[Decimal('3')]
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
There is a number of strategies to fix the problem. The most
|
|
|
|
radical is to change ``__repr__`` so it accepts a new parameter (flag)
|
|
|
|
"called from ``str``, so call ``str`` on items, not ``repr``". The
|
|
|
|
drawback of the proposal is that every ``__repr__`` implementation
|
|
|
|
must be changed. Introspection could help a bit (inspect ``__repr__``
|
|
|
|
before calling if it accepts 2 or 3 parameters), but introspection
|
|
|
|
doesn't work on classes written in C, like all built-in containers.
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
Less radical proposal is to implement ``__str__`` methods for built-in
|
|
|
|
container types. The obvious drawback is a duplication of effort - all
|
|
|
|
those ``__str__`` and ``__repr__`` implementations are only differ
|
|
|
|
in one small detail - if they call ``str`` or ``repr`` on items.
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
The most conservative proposal is not to change str at all but
|
|
|
|
to allow developers to implement their own application- or
|
|
|
|
library-specific pretty-printers. The drawback is again
|
|
|
|
a multiplication of effort and proliferation of many small
|
|
|
|
specific container-traversal algorithms.
|
2008-05-29 17:03:57 -04:00
|
|
|
|
|
|
|
|
|
|
|
Backward compatibility
|
2017-02-02 12:58:49 -05:00
|
|
|
======================
|
|
|
|
|
|
|
|
In those cases where type information is more important than
|
|
|
|
usual, it will still be possible to get the current results by
|
|
|
|
calling ``repr`` explicitly.
|
|
|
|
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
References
|
|
|
|
==========
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
.. [1] Guido van Rossum, PEP: str(container) should call str(item), not
|
|
|
|
repr(item)
|
|
|
|
http://mail.python.org/pipermail/python-3000/2008-May/013876.html
|
2008-05-29 17:03:57 -04:00
|
|
|
|
|
|
|
Copyright
|
2017-02-02 12:58:49 -05:00
|
|
|
=========
|
2008-05-29 17:03:57 -04:00
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
This document has been placed in the public domain.
|
2008-05-29 17:03:57 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
2017-02-02 12:58:49 -05:00
|
|
|
..
|
|
|
|
Local Variables:
|
|
|
|
mode: indented-text
|
|
|
|
indent-tabs-mode: nil
|
|
|
|
sentence-end-double-space: t
|
|
|
|
fill-column: 70
|
|
|
|
coding: utf-8
|
|
|
|
End:
|