[Python-3000] More PEP 3101 changes incoming

Eric Smith eric+python-dev at trueblade.com
Fri Aug 10 17:26:55 CEST 2007


Jim Jewett wrote:
> On 8/9/07, Eric V. Smith <eric+python-dev at trueblade.com> wrote:
> 
>> If you want:
>>
>> x = 3
>> "{0:f}".format(x)
>>
>> then be explicit and write:
>>
>> "{0:f}".format(float(x))
> 
> Because then you can't really create formatting strings.  Instead of
> 
>     >>> print("The high temperature at {place:s}, on {date:YYYY-MM-DD}
> was {temp:f}" % tempsdict)
>     >>> print("{name} scored {score:f}" % locals())
> 
> You would have to write
> 
>     >>> _tempsdict_copy = dict(tempsdict)
>     >>> _tempsdict_copy['place'] = str(_tempsdict_copy['place'])
>     >>> _tempsdict_copy['date'] =
>     ...         datetime.date(_tempsdict_copy['date']).isoformat()
>     >>> _tempsdict_copy['temp'] = float(_tempsdict_copy['temp'])
>     >>> print("The high temperature at {place}, on {date} was {temp}"
> % _tempsdict_copy)
> 
>     >>> _f_score = float(score)
>     >>> print("{name} scored {score}" % locals())
> 
> -jJ
> 

I concede your point that while using dictionaries it's convenient not 
to have to convert types manually.

However, your date example wouldn't require conversion to a string, 
since YYYY-MM would just be passed to datetime.date.__format__().  And
"{score}" in your second example would need to be changed to "{_f_score}".


Anyway, if we're keeping conversions, I see two approaches:

1: "".format() (or Talin's format_field, actually) understands which 
types can be converted to other types, and does the conversions.  This 
is how Patrick and I wrote the original PEP 3101 sandbox prototype.

2: each type's __format__ function understands how to convert to some 
subset of all types (int can convert to float and decimal, for example).

I was going to argue for approach 2, but after describing it, it became 
too difficult to understand, and I think I'll instead argue for approach 
1.  The problem with approach 2 is that there's logic in 
int.__format__() that understands float.__format__() specifiers, and 
vice-versa.  At least with approach 1, all of this logic is in one place.

So I think format_field() has logic like:

def format_field(value, specifier):
     # handle special repr case
     if is_repr_specifier(specifier):
         return value.__repr__()

     # handle special string case
     if is_string_specifier(specifier):
         return str(value).__format__(specifier)

     # handle built-in conversions
     if (isinstance(value, (float, basestring))
           and is_int_specifier(specifier)):
         return int(value).__format__(specifier)
     if (isinstance(value, (int, basestring)
           and is_float_specifier(specifier)):
         return float(value).__format__(specifier)

     # handle all other cases
     return value.__format__(specifier)

This implies that string and repr specifiers are discernible across all 
types, and int and float specifiers are unique amongst themselves.  The 
trick, of course, is what's in is_XXX_specifier.

I don't know enough about decimal to know if it's possible or desirable 
to automatically convert it to other types, or other types to it.

Eric.




More information about the Python-3000 mailing list