[Python-3000] PEP 3101 clarification requests

Eric Smith eric+python-dev at trueblade.com
Tue Aug 21 11:55:23 CEST 2007


Greg Ewing wrote:
> Guido van Rossum wrote:
>> But how often will you need this? (You only need the !s part if you
>> don't know that the argument is a string.)
>> Maybe I'm confused. I thought we had agreed that most
> types would delegate to str if they didn't understand
> the format, so most of the time there wouldn't be any
> need to use "!s". Is that still true?

Yes, it is true. Here's a working test case:
 # class with __str__, but no __format__
 class E:
 def __init__(self, x):
 self.x = x
 def __str__(self):
 return 'E(' + self.x + ')'
 self.assertEqual('{0}'.format(E('data')), 'E(data)')
 self.assertEqual('{0:^10}'.format(E('data')), ' E(data) ')
 self.assertEqual('{0:^10s}'.format(E('data')), ' E(data) ')
The formatting in all 3 cases is being done by string.__format__() 
(actually object.__format__, which calls str(o).__format__).
> If not, I think it will be very inconvenient, as I
> very frequently format things of all sorts of types
> using "%s", and rely on it doing something reasonable.

That will continue to work, for objects that don't provide a __format__ 
function. The problem is that if an object does does its own 
__format__, it either needs to understand all of the string formatting, 
or at least recognize a string format and send it along to 
string.__format__() (or object.__format__, which will convert to string 
for you). Another working test case:
 # class with __format__ that forwards to string,
 # for some format_spec's
 class G:
 def __init__(self, x):
 self.x = x
 def __str__(self):
 return "string is " + self.x
 def __format__(self, format_spec):
 if format_spec == 's':
 return 'G(' + self.x + ')'
 return object.__format__(self, format_spec)
 self.assertEqual('{0:s}'.format(G('data')), 'G(data)')
 # unknown spec, will call object.__format__, which calls str()
 self.assertEqual('{0:>15s}'.format(G('data')), ' string is data')
 # convert to string explicitely, overriding G.__format__
 self.assertEqual('{0!s}'.format(G('data')), 'string is data')
Note the collision with the 's' format_spec in this example. You'd have 
to carefully design your object's __format__ specifiers to be able to 
recognize string specifiers as being different from own specifiers 
(something that G does not cleanly do).
int is like G: it defines its own __format__. "!s" says: skip the 
object's own __format__ function, just convert the object to a string 
and call string.__format__. So what Guido is saying is that for int, 
instead of having int.__format__ recognize string formatting specifiers 
and doing the conversion to string, you need to convert it to a string 
yourself with "!s".
Whether that's better or not, I leave up to Guido. I personally think 
that for int and float, having them recognize "s" format specs is 
sufficiently handy that it's worth having, but I understand not 
providing that feature.
Eric.


More information about the Python-3000 mailing list

AltStyle によって変換されたページ (->オリジナル) /