classification
Title: String interpolation with unicode subclass fails to call __str__
Type: behavior Stage: test needed
Components: Interpreter Core Versions: Python 3.1, Python 3.2, Python 2.7, Python 2.6
process
Status: closed Resolution: duplicate
Dependencies: Superseder: __str__ cannot be overridden on unicode-derived classes
View: 1583863
Assigned To: benjamin.peterson Nosy List: Arfrever, benjamin.peterson, eric.smith, ezio.melotti, flox, georg.brandl, steven.daprano
Priority: normal Keywords:

Created on 2010-03-13 02:47 by steven.daprano, last changed 2010-04-27 14:45 by eric.smith. This issue is now closed.

Files
File name Uploaded Description Edit
test_interpolation.py steven.daprano, 2010-03-20 10:04
Messages (6)
msg100984 - (view) Author: Steven D'Aprano (steven.daprano) * (Python committer) Date: 2010-03-13 02:47
String interpolation % operates on unicode strings directly without calling the __str__ method. In Python 2.5 and 2.6:

>>> class K(unicode):
...     def __str__(self): return "Surprise!"
...
>>> u"%s" % K("some text")
u'some text'

but subclasses of str do call __str__:

>>> class K(str):
...     def __str__(self): return "Surprise!"
...
>>> "%s" % K("some text")
'Surprise!'

In Python 3.1, the above example for subclassing str operates like the unicode example, i.e. it fails to call __str__.

The documentation for string interpolation states that str() is called for all Python objects.

http://docs.python.org/library/stdtypes.html#string-formatting-operations

If the behaviour for unicode (2.5/2.6, str in 3.1) is considered correct, then the documentation should be updated to say that unicode is an exception to the rule. Otherwise the behaviour is incorrect, and it should call __str__ the same as everything else.
msg101369 - (view) Author: Steven D'Aprano (steven.daprano) * (Python committer) Date: 2010-03-20 10:04
I've assumed that the documentation is correct, and that "%s"%obj should call __str__ for unicode objects as well as everything else.

Attached in a test file.
msg104299 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2010-04-27 07:09
In Python 2.x, __unicode__ is called instead of __str__.  Whether that's "correct" behavior, I'm not sure, but at least it is consistent with "{}".format(K()).

In Python 3.x, __unicode__ doesn't exist and __str__ isn't called; but for "{}".format(K()), it is.  Therefore I think here a fix should be made in any case.

Benjamin, what do you think?
msg104304 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2010-04-27 09:27
I agree with Georg. I think 2.x is arguably correct, and 3.1 is broken.

It looks like this has already been fixed in 3.2. It's not immediately obvious why that is, I'll have to look at the code more than the quick glance I just gave it.

Python 3.1.1+ (release31-maint:77299, Jan  4 2010, 08:27:32) 
[GCC 4.1.2 20070626 (Red Hat 4.1.2-13)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> class MyStr(str):
...     def __str__(self): return "Surprise!"
... 
>>> '%s' % MyStr('foo')
'foo'
>>> '{}'.format(MyStr('foo'))
'Surprise!'

Python 3.2a0 (py3k:80525M, Apr 27 2010, 05:19:53) 
[GCC 4.1.2 20070626 (Red Hat 4.1.2-13)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> class MyStr(str):
...     def __str__(self): return "Surprise!"
... 
>>> '%s' % MyStr('foo')
'Surprise!'
>>> '{}'.format(MyStr('foo'))
'Surprise!'
msg104323 - (view) Author: Arfrever Frehtes Taifersar Arahesis (Arfrever) * Date: 2010-04-27 14:13
It's probably a duplicate of issue #1583863.
msg104326 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2010-04-27 14:45
Yes, that's the cause, thanks for finding that issue. It's actually fixed in 3.1.2, I just hadn't updated my local copy.

Closing, since there's nothing to fix here. The 2.6 behavior is correct, and the 3.x behavior that was broken has been fixed.
History
Date User Action Args
2010-04-27 14:45:23eric.smithsetstatus: open -> closed
resolution: duplicate
superseder: __str__ cannot be overridden on unicode-derived classes
messages: + msg104326
2010-04-27 14:13:14Arfreversetnosy: + Arfrever
messages: + msg104323
2010-04-27 09:27:46eric.smithsetmessages: + msg104304
2010-04-27 07:09:22georg.brandlsetassignee: benjamin.peterson

messages: + msg104299
nosy: + benjamin.peterson, georg.brandl
2010-03-20 10:04:36steven.dapranosetfiles: + test_interpolation.py

messages: + msg101369
2010-03-13 09:20:13floxsetnosy: + flox
2010-03-13 08:45:20eric.smithsetnosy: + eric.smith
2010-03-13 06:50:05ezio.melottisetnosy: + ezio.melotti
versions: + Python 2.7, Python 3.2, - Python 2.5
priority: normal
components: + Interpreter Core
type: behavior
stage: test needed
2010-03-13 02:47:32steven.dapranocreate