[Python-3000] PEP 3101 update

Nick Coghlan ncoghlan at gmail.com
Sun Jun 11 07:31:18 CEST 2006


Talin wrote:
> Conversion Specifiers
> 
>      Each field can also specify an optional set of 'conversion
>      specifiers' which can be used to adjust the format of that field.
>      Conversion specifiers follow the field name, with a colon (':')
>      character separating the two:
> 
>          "My name is {0:8}".format('Fred')
> 
>      The meaning and syntax of the conversion specifiers depends on the
>      type of object that is being formatted, however many of the
>      built-in types will recognize a standard set of conversion
>      specifiers.

Given the changes below, this paragraph should now read something like,

      The meaning and syntax of the conversion specifiers depends on the
      type of object that is being formatted, however there is a standard set
      of conversion specifiers used for any object that does not override
      them.

> 
>      Conversion specifiers can themselves contain replacement fields.
>      For example, a field whose field width it itself a parameter
>      could be specified via:

Typo: s/width it itself/width is itself/

>      The syntax for conversion specifiers is open-ended, since except
>      than doing field replacements, the format() method does not
>      attempt to interpret them in any way; it merely passes all of the
>      characters between the first colon and the matching brace to
>      the various underlying formatter methods.

Again, this paragraph has been overtaken by events.

       The syntax for conversion specifiers is open-ended, since a class can
       override the standard conversion specifiers. In such cases, the format()
       method merely passes all of the characters between the first colon and
       the matching brace to the relevant underlying formatting method.

> Standard Conversion Specifiers

It's probably worth avoiding describing the elements of the conversion 
specifier as fields - something neutral like 'element' should do.


>          '=' - Forces the padding to be placed between immediately
>                after the sign, if any. This is used for printing fields
>                in the form '+000000120'.

Typo: s/placed between immediately/placed immediately/

>      The 'precision' field is a decimal number indicating how many
>      digits should be displayed after the decimal point.

Someone pointed out that for string conversions ('s' & 'r'), this field should 
determine how many characters are displayed.

      The 'precision' is a decimal number indicating how many digits should be
      displayed after the decimal point in a floating point conversion. In a
      string conversion the field indicates how many characters will be used
      from the field content. The precision is ignored for integer conversions.

>      There are several integer conversion types. All invoke int() on
>      the object before attempting to format it.

Having another look at existing str-% behaviour, this should instead say:

       There are several integer conversion types. All will raise TypeError
       if the supplied object does not have an __index__ method.

>      There are several floating point conversion types. All invoke
>      float() on the object before attempting to format it.

Similar to integers, this should instead say:

       There are several floating point conversion types. All will raise
       TypeError if the supplied object is not a float or decimal instance.

> Controlling Formatting

I'm becoming less and less satisfied with the idea that to get a string 
version of a float, I do this:

   x = str(val)

But if I want to control the precision, I have to write:

   x = "{0:.3}".format(val)  # Even worse than the current "%.3f" % val!!

Why can't I instead write:

   x = str(val, ".3")

IOW, why don't we change the signature of 'str' to accept a conversion 
specifier as an optional second argument?

Then the interpretation of conversion specifiers in format strings is 
straightforward - the conversion specifier becomes the second argument to str().

Then it would be str() that does the dispatch of the standard conversion 
specifiers as described above if __format__ is not provided.

Here's the description of controlling formatting in that case:

------------------------------------------------
Controlling Formatting
      A class that wishes to implement a custom interpretation of its
      conversion specifier can implement a __format__ method:

      class AST:
          def __format__(self, specifier):
              ...

     str.format() will always format each field by invoking str() with two
     arguments: the value to be formatted and the conversion specifier. If the
     field does not include a conversion specifier then it defaults to None.

     The signature of str() is updated to accept a conversion specifier as the
     second argument (defaulting to None). When the conversion specifier is
     None, the __str__() method of the passed in object is invoked (if present)
     falling back to __repr__() otherwise (aside from using unicode instead of
     8-bit strings, this is unchanged from Python 2.x).

     If the conversion specifier is not None, then the object's __format__()
     method is invoked if present. Otherwise, the standard conversion
     specifiers described above are used.

     This means that where, in Python 2.x, controlling the precision of a
     float's string output required switching from the str() builtin to string
     formatting, Python 3k permits the conversion specifier to be added to the
     call to the builtin.

       x = str(val)         # Unformatted
       x = str(val, '.3')   # Limited to 3 decimal places

     This works for types with custom format specifiers, too:

          today = str(datetime.now(), 'a b d H:M:S Y')

> User-Defined Formatting Classes
> 
>      There will be times when customizing the formatting of fields
>      on a per-type basis is not enough.  An example might be an
>      accounting application, which displays negative numbers in
>      parentheses rather than using a negative sign.

This is now a bad example, because we moved it into the standard conversion 
specifiers :)

>      The format hook is a callable object supplied by the user, which
>      is invoked once per field, and which can override the normal
>      formatting for that field.  For each field, the cformat function
>      will attempt to call the field format hook with the following
>      arguments:
> 
>         format_hook(value, conversion)

With my str() proposal above, the default format hook becomes 'str' itself.

Cheers,
Nick.

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


More information about the Python-3000 mailing list