New Python 3.0 string formatting - really necessary?
MRAB
google at mrabarnett.plus.com
Sun Dec 21 11:31:51 EST 2008
Aaron Brady wrote:
> On Dec 20, 8:49 pm, MRAB <goo... at mrabarnett.plus.com> wrote:
>> Aaron Brady wrote:
>>> On Dec 20, 7:38 pm, Steven D'Aprano <st... at REMOVE-THIS-
>>> cybersource.com.au> wrote:
>>>> Instead of just whinging, how about making a suggestion to fix it? Go on,
>>>> sit down for an hour or ten and try to work out how a BINARY OPERATOR
>>>> like % (that means it can only take TWO arguments) can deal with an
>>>> arbitrary number of arguments, *without* having any special cases.
>>>> Go on. Take your time. I'll be waiting.
>>> Hi, not to take sides, but, there is a possibility.
>>> This behavior is currently legal:
>>>>>> "%i %%i" % 0 % 1
>>> '0 1'
>>> So, just extend it. (Unproduced.)
>>>>>> "%i %i" % 0 % 1
>>> '0 1'
>>>>>> "%r %i" % (2, 3, 4) % 1
>>> '(2, 3, 4) 1'
>>>>>> "%r %i" % (2, 3, 4)
>>> '(2, 3, 4) %i'
>>> Which is quite clever and way ahead of its (posessive) time.
>> A couple of problems:
>>
>> 1. How do you handle a literal '%'? If you just double up then you'll
>> need to fix the string after all your substitutions.
>>
>> 2. What if a substitution introduces a '%'?
>>
>> I suppose a possible solution would be to introduce a special format
>> string, including a literal, eg:
>>
>> f"%r %i" % (2, 3, 4) % 1
>>
>> and then convert the result to a true string:
>>
>> print(str(f"%r %i" % (2, 3, 4) % 1))
>>
>> (although print() would call __str__ anyway).
>>
>> The format string would track where the last substitution occurred.
>>
>> Hmm... I think I'll just learn the new method. :-)
>
> Now that I'm fighting 'r's war for him/her...
>
> Um, here's one possibility. On the first interpolation, flags are
> noted and stored apart from subsequent interpolations. Then, use a
> sentinel to terminate the interpolation. (Unproduced.)
>
>>>> "%r %i" % ( 2, 3 ) % 0
> '(2, 3) 0'
>>>> "%% %r" % ( 2, 3 ) % str.interp_end
> '% (2, 3)'
>>>> "%sss%i" % "%d" % 0
> '%dss0'
>
> The first %s is replaced with %d, but doesn't hijack the '0'. If you
> want to interpolate the %d, use the sentinel. The sentinel is what
> causes '%%' to be handled.
>
>>>> "%sss%i" % "%d" % 0 % 1
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> TypeError: not all arguments converted during string formatting
>>>> "%sss%i" % "%d" % 0 % str.interp_end % 1
> '1ss0'
>
> Treating tuples as a special case appears to be the simpler solution,
> but this, 'chaining', to adopt the term, is still feasible.
>
A possible solution occurred to me shortly after I posted, but I decided
that sleep was more important. :-)
The original format is a string. The result of '%' is a string if
there's only 1 placeholder to fill, or a (partial) format object (class
"Format"?) if there's more than one. Similarly, the format object
supports '%'. The result of '%' is a string if there's only 1
placeholder to fill, or a new (partial) format object if there's more
than one.
>>> f = "%r %i"
>>> type(f)
<type 'str'>
>>> f = f % (2, 3, 4)
>>> type(f)
<type 'Format'>
>>> f = f % 1
>>> type(f)
<type 'str'>
More information about the Python-list
mailing list