[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