""" Figure out how __str__ and __unicode__ class methods are used when str() and unicode() are called on the class, in all combinations. I submitted a bug re Python documentation for this: http://bugs.python.org/issue9196 Example 1: "%s" % test_object From what I can tell, in this case: 1. test_object.__str__() is called. 2. If test_object.__str__() returns a string object, then that is substituted. 3. If test_object.__str__() returns a Unicode object (for some reason), then test_object.__unicode__() is called, then _that_ is substituted instead. The output string is turned into Unicode. This behaviour is surprising. 4. If test_object.__str__() returns a Unicode object (for some reason), and test_object.__unicode__() does not exist, then the Unicode value from the __str__() call is used as-is (no conversion to string, no encoding errors). This is also a little surprising [in this situation unicode(test_object) also returns the Unicode object returned by __str__() as-is, so I guess there's some consistency there]. [Note that the call to test_object.__str__() is not the same as str(test_object), because the former can return a Unicode object without causing an error, while the latter, if it gets a Unicode object, will then try to encode('ascii') to a string, possibly generating a UnicodeEncodeError exception.] Example 2: u"%s" % test_object In this case: 1. test_object.__unicode__() is called, if it exists, and the result is substituted. The output string is Unicode. 2. If test_object.__unicode__() doesn't exist, then test_object.__str__() is called instead, converted to Unicode, and substituted. The output string is Unicode. Example 3: "%s %s" % (u'unicode', test_object) In this case: 1. The first substitution causes the output string to be Unicode. 2. It seems that (1) causes the second substitution to follow the same rules as Example 2. This is a little surprising. """ class TestObject: def __str__(self): return u"String\u4422" # def __unicode__(self): # return u"Unicode" test_object = TestObject() out = "%s %s" % ('str', test_object) print "__str__():", repr(test_object.__str__()) print "out:", repr(out) print "type(out):", type(out) #print "str():", repr(str(test_object)) print "unicode():", repr(unicode(test_object))