[Python-3000] PEP - string.format
Ian Bicking
ianb at colorstudy.com
Sun Apr 23 21:06:51 CEST 2006
Nick Coghlan wrote:
> [...]
>> The second method, 'fformat', is identical to the first, except that it
>> takes an additional first argument that is used to specify a 'custom
>> formatter' object, which can override the normal formatting rules for
>> specific fields:
>>
>> "More on {0}, {1}, and {c}".fformat( formatter, a, b, c=d )
>>
>> Note that the formatter is *not* counted when numbering fields, so 'a' is
>> still considered argument number zero.
>
> I don't like this. Formatting with a different formatter should be done as a
> method on the formatter object, not as a method on the string.
+1. Plus "fformat" doesn't really mean anything as a name (as least to me).
But this should perform pretty well if it's going to replace % (which
wouldn't have to happen for Python 2.6, but should for py3k).
> [...]
>> Braces can be escaped using a backslash:
>>
>> "My name is {0} :-\{\}".format( 'Fred' )
>
> So "My name is 0} :-\{\}".format('Fred') would be an error? I like that - it
> means you get an immediate exception if you inadvertently leave out a brace,
> regardless of whether you leave out the left brace or the right brace.
I kind of like that too, even though } doesn't really have to be quoted.
It always weird me out that > doesn't have to be quoted in XML.
It occurs to me that the overloading of \ might cause some
complications; % and string.Template use doubling (%% and $$). For
instance, a little help message:
write("To include the username ({username}) use \{username\}\n"
"and use \\\{ and \\\} to include literal
brackets".format(username=u))
Which I isn't all that bad. I assume other \ sequences won't be
interpretted. I.e., "\\n".format() produces "\\n". But I then don't
see any way to do "\\%s" % var.
>> The format() method does not attempt to interpret the
>> conversion specifiers in any way; it merely passes all of the characters
>> between the first colon ':' and the matching right brace ('}') to the
>> various underlying formatters (described later.)
>
> If we had a subclassing API similar to what I suggest above, a custom
> formatter could easily support Ian's pipelining idea by doing:
>
> def format_value(self, value, fmt_spec):
> if fmt_spec is None:
> val = Formatter.format_value(self, value, fmt_spec)
> else:
> for fmt in fmt_spec.split(':'):
> val = Formatter.format_value(self, value, fmt_spec)
> return val
>
> I don't really think that should be the default, though.
It won't work if the __format__ conventions don't support it; if all
objects return strings then pipelining will become much less useful.
> [...]
>> - The trailing letter is optional - you don't need to say '2.2d', you can
>> instead just say '2.2'. If the letter is omitted, then the value will be
>> converted into its 'natural' form (that is, the form that it take if str()
>> or unicode() were called on it) subject to the field length and precision
>> specifiers (if supplied.)
>
> I disagree with this. These format specifier do a type coercion before
> applying the formatting. These specifiers should be retained and should
> continue to result in coercion to int or float or str, with the relevant
> TypeErrors when that coercion isn't possible.
-1. I think %d is silly in Python, and we shouldn't replicate that here.
>> 2) Otherwise, see if the value to be formatted has a __format__ method. If
>> it does, then call it.
>
> So an object can override standard parsing like {0:d} to return something
> other than an integer? *shudder*
"{0:d}" doesn't scream "integer" to me. %d does because of history, but
only because of history.
> Being able to add extra formatting codes for different object types sounds
> good, but being able to change the meaning of the standard codes sounds (very)
> bad.
There are no standard codes. There's standard % codes, but this isn't %.
> If supporting the former also means supporting the latter, then I'd prefer to
> leave this ability to custom formatter objects or explicit method or function
> invocations on arguments in the call to format().
>
>> 3) Otherwise, check the internal formatter within string.format that
>> contains knowledge of certain builtin types.
>
> This should happen *before* checking for a custom __format__ method. (If we
> decide to check for a custom __format__ method at all)
How would this change anything? Presumably only the immutable types
(int, str, list, etc) would be specially handled anyway.
> [...]
>> One other thing that could be done to make the debugging case more
>> convenient would be to allow the locals() dict to be omitted entirely.
>> Thus, a format function with no arguments would instead use the current
>> scope as a dictionary argument:
>>
>> print "Error in file {p.file}, line {p.line}".format()
>
> Again, I don't think this is worth the additional complexity.
I don't really understand the complexity argument; I think you should be
more specific about what becomes more complex.
> [...]
>> Other, more radical proposals include backquoting (`), or a new string
>> prefix character (let's say 'f' for 'format'):
>>
>> print f"Error in file {p.file}, line {p.line}"
>
> A method will do the job with far more flexibility - no need to hack the parser.
In this particular case (where locals() are picked up implicitly) a
method has several flaws. I don't think the f"" syntax makes any sense
outside of that case; so it's a separate argument (*if* there's support
for a special form evaluated in the scope where the string came from,
then will it use f""?)
--
Ian Bicking | ianb at colorstudy.com | http://blog.ianbicking.org
More information about the Python-3000
mailing list