[Python-3000] PEP 3101 update

Nick Coghlan ncoghlan at gmail.com
Sat Jun 24 04:47:40 CEST 2006


Guido van Rossum wrote:
 >  "foo{2.2g}bar{3.3f}spam".format(x, y)

Getting a format string like that to work would be tricky. With the current 
PEP, it would need to be:

   "foo{0:2.2g}bar{1:3.3f}spam".format(x, y)

It should be possible to simplify that without ambiguity to:

   "foo{:2.2g}bar{:3.3f}spam".format(x, y)

by having an internal counter in the format function that kept track of how 
many fields had been encountered that didn't refer to a specific position or 
name. That is, either the braces were empty ('{}'), or there was nothing 
before the conversion specifier ('{:<spec>}').

To get shorter than that, however, you'd be getting into territory where the 
interpreter is trying to guess the programmer's intent (e.g. is '{0f}' 
intentionally just a conversion specifier, or is it a typo for '{0:f}'?). So I 
think going that far falls foul of EIBTI, the same way my idea of an implicit 
"{0:" and "}" did.

I like the internal counter concept though - it means that purely positional 
stuff can be written without any additional mental overhead, and with the 
braces being the only additional typing when compared to the status quo.

That way, if you didn't have any field formatting you wanted to do, you could 
just write:

   "{} picks up the {}. It is {}!".format(person, thing, adjective)

> I'm not sure that every object should have this method.
> 
> Please consider making it just a method in a stdlib module.
> 
> Perhaps it could use overloaded functions.
> 
> IMO the PEP would do best not to add new builtins or object methods.
> (A __format__ method is OK since it just mimics the standard idiom for
> providing overridable type-specific operations; but perhaps
> overloadable functions are a better alternative.)

Since the PEP calls "2.2g" and friends conversion specifiers, how about we use 
an overloaded function "string.convert"?

   # In string.py
   @overloaded
   def convert(obj, spec):
       """Converts an object to a string using a conversion specifier"""
       # Default handling is to convert as per PEP 3101
       #   (AKA the "format_builtin_type" function in Talin's prototype)


Objects with alternate conversion specifiers (like datetime objects) would 
simply overload the function:

   # In datetime.py
   @atimport("string")
   def _string_overloads(module):
       """Register function overloads in string module"""
       overload(module.convert, time)(time.strftime)
       overload(module.convert, date)(date.strftime)
       overload(module.convert, datetime)(datetime.strftime)

The "cformat" function from Talin's prototype could then be named 
"string.format", with the signature:

   # In string.py
   def format(fmt, positional=(), named=None, field_hook=None):
       """Create a formatted string from positional and named values"""
       # Format as per PEP 3101
       #   (AKA the "cformat" function in Talin's prototype)

Finally, the format method of str objects would use the above:

   # Method of str objects
   def format(self, *args, **kwds):
       from string import format
       return format(self, args, kwds)

So if you had an existing tuple and/or dictionary, you could do "from string 
import format" and use the function directly in order to save creation of an 
unnecessary copy of the containers.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia
---------------------------------------------------------------
             http://www.boredomandlaziness.org


More information about the Python-3000 mailing list