Interpolation surprise
Every moderately proficient Python programmer probably knows that these two snippets are equivalent:
(The 1-tuple in the first case is to make this equivalent even for tuples.)
Surely, these are equivalent as well?
I think it should by now by apparent what the surprise is :)
"%s" % (obj,) "%s" % str(obj)
Now, what about this:
"%s %s" % (a, b) "%s %s" % (str(a), str(b))
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)
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.
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 #
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 #