[Python-3000] More PEP 3101 changes incoming

Ron Adam rrr at ronadam.com
Sat Aug 4 02:12:17 CEST 2007



Talin wrote:

> What's missing, however, is a description of how all of this interacts 
> with the __format__ hook. The problem we are facing right now is 
> sometimes we want to override the __format__ hook and sometimes we 
> don't. Right now, the model that we want seems to be:
> 
>   1) High precedence type coercion, i.e. 'r', which bypasses __format__.
>   2) Check for __format__, and let it interpret the format specifier.
>   3) Regular type coercion, i.e. 'd', 'f' and so on.
>   4) Regular formatting based on type.

A few more thoughts regarding this..

We can divide these into concrete and abstract type specifiers.

Concrete type specifiers only accept a specific type.  They would raise an 
exception if the argument is of another type.  Concrete type specifiers 
would always passed to an objects __format__ method.


Abstract type specifications are more lenient and work with a wider range 
of objects because they use duck typing.

So that splits things up as follows...

(I added an abstract 't' text type, to resolve the ambiguity of the 's' 
type either calling __format__ or __str__)


Concrete type specifiers:

     s -  string type   (not the __str__ method in this case)

     b,c,d,o,x,X - int type

     e,E,f,F - float type


Abstract types specifiers:  (uses duck typing)

     ! -  calls __format__ method,  fallbacks... (__str__, __repr__)
     t -  (text) calls __str__ method,  no fallback
     r -  calls __repr__ method, fallback (__str__)

The '!' type could be the default if no type is specified, it is needed if 
you also specify any formatting options.

    '{0:!xyz}'

So '!xyz' would be passed to the __format__ method if it exists and it 
would be up to that type to know what to do with the xyz.  The format_spec 
wouldn't be passed to __str__ or __repr__.

Should there be an abstract numeric type?  These would call an objects 
__int__ or __float__ method if it exists.

One of the things I've noticed is you have 'd' instead of 'i'.  Maybe 'i' 
should be the concrete integer type, and 'd' and abstract integer type that 
calls an objects __int__ method.  Then we would need a floating point 
abstract type that calls __float__ ... 'g'?

In the case of an abstract type that does a conversion the format spec 
could be forwarded to the objects __format__ method of the returned object.


Then we have the following left over...

         'g' - General format. This prints the number as a fixed-point
               number, unless the number is too large, in which case
               it switches to 'e' exponent notation.
         'G' - General format. Same as 'g' except switches to 'E'
               if the number gets to large.
         'n' - Number. This is the same as 'g', except that it uses the
               current locale setting to insert the appropriate
               number separator characters.
         '%' - Percentage. Multiplies the number by 100 and displays
               in fixed ('f') format, followed by a percent sign.

Now I'm not sure how to best handle these.  Are they abstract and call a 
particular __method__, or are they concrete and always call __format__ on a 
particular type?


Cheers,
    Ron







More information about the Python-3000 mailing list