new string-formatting preferred? (was "What is this syntax ?")
Terry Reedy
tjreedy at udel.edu
Tue Jun 21 18:19:26 EDT 2011
On 6/21/2011 7:33 AM, Tim Chase wrote:
> On 06/20/2011 09:17 PM, Terry Reedy wrote:
>> On 6/20/2011 8:46 PM, Tim Chase wrote:
>>> On 06/20/2011 05:19 PM, Ben Finney wrote:
>>>> “This method of string formatting is the new standard in
>>>> Python 3.0, and should be preferred to the % formatting
>>>> described in String Formatting Operations in new code.”
>>>>
>>>> <URL:http://docs.python.org/library/stdtypes.html#str.format>
>>>
>>> Is there a good link to a thread-archive on when/why/how .format(...)
>>> became "preferred to the % formatting"?
>>
>> That is a controversial statement.
>
> I'm not sure whether you're "controversial" refers to
>
> - the documentation at that link,
> - Ben's quote of the documentation at that link,
> - my quotation of Ben's quote of the documentation,
> - or my request for a "thread-archive on the when/why/how"
>
> I _suspect_ you mean the first one :)
I meant the preceding statement (derived from the linked source, but
that is not important) that .format is preferred to %. Guido prefers it.
I prefer it. At least a couple of developers vocally do not prefer it
and might prefer that the statement was not there. Guido recognizes that
deprecation of % formatting would at least require a conversion function
that does not now exist.
I see that the linked doc says 'in new code'. That makes the statement
less (but only less) controversial.
>
>>> I haven't seen any great wins of the new formatting over
>>> the classic style.
>>
>> It does not abuse the '%' operator,
>
> Weighed against the inertia of existing code/documentation/tutorials, I
> consider this a toss-up. If .format() had been the preferred way since
> day#1, I'd grouse about adding/overloading '%', but going the other
> direction, there's such a large corpus of stuff using '%', the addition
> of .format() feels a bit schizophrenic.
>
>> it does not make a special case of tuples (a source of bugs),
>
> Having been stung occasionaly by this, I can see the benefit here over
> writing the less-blatant
>
> "whatever %s" % (tupleish,)
>
>> and it is more flexible, especially
>> indicating objects to be printed. Here is a simple example from my code
>> that would be a bit more difficult with %.
>>
>> multi_warn = '''\
>> Warning: testing multiple {0}s against an iterator will only test
>> the first {0} unless the iterator is reiterable; most are not.'''.format
>> ...
>> print(multiwarn('function'))
>> ...
>> print(multiwarn('iterator'))
>
> Does the gotcha of a non-restarting iterator
Huh? What iterator?
> trump pulling each field you want and passing it explicitly?
Huh? I explicitly pass the strings to be printed.
> In pre-.format(), I'd just use dictionary formatting:
>
> "we have %(food)s & eggs and %(food)s, bacon & eggs" % {
> "food": "spam", # or my_iterator.next()?
> }
A better parallel to my example would be
menu = "We have %(meat)s & eggs or %(meat)s and potatoes."
print(menu % {'meat':'spam'})
print(menu % {'meat':'ham'})
The exact duplicate of that with .format is
menu = "We have {meat} & eggs or {meat} and potatoes.".format
print(menu(meat = 'spam'))
print(menu(meat = 'ham'))
One knock against '.format' is that it is 6 chars more that '%'. But for
repeat usage, it is only needed once. And look: '%(meat)s' is 2 more
chars than '{meat}' and, to me, {} is easier to type than (). Then " %
{'meat':"spam"}" is 3 more chars than "(meat = 'ham')" and definitely
harder to type. While I prefer '}' to ')', I prefer '))' to the mixed
'})'. The % way is at least 'a bit more difficult' even compared to the
longer and harder .format with named fields.
menu = "We have {0} & eggs or {0} and potatoes.".format
print(menu('spam'))
print(menu('ham'))
it a little easier yet, though perhaps less clear, especially if there
were multiple substitutions.
> The other new feature I saw was the use of __format__() which may have
> good use-cases, but I don't yet have a good example of when I'd want
> per-stringification formatting compared to just doing my desired
> formatting in __str__() instead.
__str__ always returns the same string for an instance in a given state.
Similarly, __float__ and __int__ will return the same float or int
version of an unchanged instance. __format__(spec) can directly adjust
the result according to spec without the restriction of going through an
intermediary str, int, or float.
Suppose one had a Money class with currency and decimal amount fields.
.__str__ can add a currency symbol (before or after as appropriate) but
has to use a standard format for the amount field. .__float__ can be
post-processed according to a %...f spec, but cannot include a currency
symbol. Money.__format__(self,spec) can format the amount at it wishes,
including its rounding rules, *and* add a currency symbol.
Or suppose one has a multi-precision float. %80.40f will require an mpf
instance to appoximate itself as a float, possibly with error.
mpg.__format__ should be able to do better.
(Sadly, this new ability to more accurately represent objects is not yet
used for ints and is broken for fractions.Fraction. I will probably post
issues on the tracker.)
--
Terry Jan Reedy
More information about the Python-list
mailing list