[Python-3000] More PEP 3101 changes incoming

Ron Adam rrr at ronadam.com
Tue Aug 7 21:52:55 CEST 2007



Greg Ewing wrote:
> Ron Adam wrote:
>> What about mismatched specifiers?
> 
> It's not clear exactly what you mean by a "mismatched"
> specifier.
 >
> Some types may recognise when they're being passed
> a format spec that belongs to another type, and try
> to convert themselves to that type (e.g. applying
> 'f' to an int or 'd' to a float).

After thinking about this a bit more, I think specifiers don't have types 
and don't belong to types. They are the instructions to convert an object 
to a string, and to format that string in a special ways.  It seems they 
are mapped one to many, and not one to one.


> If the type doesn't recognise the format at all,
> and doesn't have a fallback type to delegate to
> (as will probably be the case with str) then
> you will get an exception.

I agree.


>> I think the opinion so far is to let the objects __format__ method 
>> determine this, but we need to figure this out what the built in types 
>> will do.
> 
> My suggestions would be:
> 
>    int - understands all the 'integer' formats
>          (d, x, o, etc.)
>        - recognises the 'float' formats ('f', 'e', etc.)
>          and delegates to float
>        - delegates anything it doesn't recognise to str
> 
>    float - understands all the 'float' formats
>          - recognises the 'integer' formats and delegates to int
>          - delegates anything it doesn't recognise to str
> 
>    str - recognises the 'string' formats (only one?)
>        - raises an exception for anything it doesn't understand
> 
> I've forgotten where 'r' was supposed to fit into
> this scheme. Can anyone remind me?

So if i want my own objects to work with these other specifiers, I need to 
do something like the following in every object?

     def __format__(self, specifier):
         if specifier[0] in ['i', 'x', 'o', etc]:
             return int(self).format(specifier)
         if specifier[0] in ['f', 'e', etc]:
             return float(self.).format(specifier)
         if specifier[0] == 'r':
             return repr(self)
         if specifier[0] == 's':
             return str(self).format(specifier)
         if specifier[0] in '...':
             ...
             ... my own specifier handler
             ...
         raise ValueError, 'invalid specifier for this object type'



I'm currently playing with a model where specifiers are objects. This seems 
to simplify some things.  The specifier object parses the specifier term 
and has a method to apply it to a value.  It can know about all the 
standard built in specifiers.

It could call an objects __format__ method for an unknown specifier or we 
can have the __format__ method have first crack at it and write the default 
__format__ method like this...

     def __format__(self, specifier):
         return specifier.apply(self)



Then we can over ride it in various ways...

     def __format__(self, specifier):
         ...
         ... my specifier handler
         ...
         return result


     def __format__(self, specifier):
         if specifier[0] in '...':
             ...
             ... my specifier handler
             ...
             return result
         return specifier.apply(self)


     def __format__(self, specifier):
	try:
             return specifier.apply(self)
         Except ValueError:
             pass
         ...
         ... my specifier handler
         ...
         return result


Or we can say the standard ones don't call your __format__ method, but if 
you use the '!' specifier, it will call your __format__ method.  More 
limiting, but much simpler.  I'm not sure I have a preference here yet.

Cheers,
    Ron









More information about the Python-3000 mailing list