New Python 3.0 string formatting - really necessary?

MRAB google at mrabarnett.plus.com
Sun Dec 21 17:58:53 CET 2008


Aaron Brady wrote:
> On Dec 21, 10:31 am, MRAB <goo... at mrabarnett.plus.com> wrote:
>> 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'>
> 
> Alright, so how are you handling:
> 
>>>> f= "%s %i"
>>>> type( f )
> <type 'str'>
>>>> f= f% '%i'  #now '%i %i'
>>>> type( f )
> <type 'Format'>
>>>> f= f% 1
>>>> type( f )
> ?
> 
> In other words, are you slipping '1' in to the very first available
> slot, or the next, after the location of the prior?
> 
Let's assume that Format objects display their value like the equivalent 
string format:

 >>> f = "%r %i"
 >>> f
'%r %i'
 >>> f = f % (2, 3, 4)
 >>> f
<Format '(2, 3, 4) %i'>
 >>> f = f % 1
 >>> f
'(2, 3, 4) 1'
 >>>
 >>> f = "%s %i"
 >>> f
'%s %i'
 >>> f = f % '%i'
 >>> f
<Format '%%i %i'>
 >>> f = f % 1
 >>> f
'%%i 1'




More information about the Python-list mailing list