And now for something completely Pythonic...

Interpolation surprise

written by Georg, on Saturday, September 12, 2009 20:08.

Every moderately proficient Python programmer probably knows that these two snippets are equivalent:
"%s" % (obj,)
"%s" % str(obj)
(The 1-tuple in the first case is to make this equivalent even for tuples.)

Now, what about this:

"%s %s" % (a, b)
"%s %s" % (str(a), str(b))
Surely, these are equivalent as well?

It turns out that they aren’t! Given this code:

class Surprise(object):
    def __str__(self):
        return "[str]"
    def __unicode__(self):
        return u"[unicode]"

surprise = Surprise()

print "%s %s" % ("foo", surprise)
print "%s %s" % (u"foo", surprise)
I think it should by now by apparent what the surprise is :)

In short, as soon as a Unicode item has been interpolated into a bytestring (which makes the result a Unicode string), further items are automatically use Unicode conversion, given by __unicode__(), if available. This came up recently on the docutils mailing list, where a test failure was triggered because Python 2.6′s IOError has a buggy __unicode__() implementation.

Comments

  1. Yeah, I just discovered this last night because when a unittest failed when I tried to:

    assert oldstr == newstr

    newstr had parts of it built up of CharFields from Django and that forced the whole shebang to unicode.

    —  John P.Speno on Sunday, September 13, 2009 13:14 #

  2. Seems like improper behavior to me to be honest. The interpolated-to string should decide which type the result will be, otherwise the whole thing becomes unpredictable.

    —  lericson on Wednesday, January 6, 2010 23:06 #

Commenting is no longer possible.