New Python 3.0 string formatting - really necessary?

Aaron Brady castironpi at gmail.com
Sun Dec 21 11:41:35 EST 2008


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?



More information about the Python-list mailing list