[Python-ideas] Briefer string format

Mike Miller python-ideas at mgmiller.net
Tue Aug 4 22:05:34 CEST 2015


Hi,

In that message there was a logical step that I don't follow:

 > For example:
 > '{a.foo}'.format(a=b[c])
 >
 > If we limit f-strings to just what str.format() string expressions can
 > represent, it would be impossible to represent this with an f-string,
 > without an intermediate assignment.

 > For example:
 > f'{a[2:3]:20d}'
 >
 > We need to extract the expression "a[2:3]" and the format spec "20d". I
 > can't just scan for a colon any more, I've got to actually parse the
 > expression until I find a "}", ":", or "!" that's not part of the
 > expression so that I know where it ends.

There was a solution to this that came up early in the discussion, moving the 
identifier only:

     f'{x}{y}'           -->  '{}{}'.format(x, y)
     f'{x:10}{y[name]}'  -->  '{:10}{[name]}'.format(x, y)

I missed the part where this was rejected.  As far as I can tell from your 
message, it is because it would be hard to parse?  But, it seems no harder than 
other solutions.  I've whipped up a simple implementation below.

Also, Guido sounds supportive of your general process, but to my knowledge has 
not explicitly called for arbitrary expressions to be included.  Perhaps he 
could do that, or encourage us to find a more conservative solution?

Sorry to be a pain, but I think this part is important to get right.

-Mike

Simple script to illustrate (just ascii, only one format op supported).

TL;DR: the idea is to grab the identifier portion by examining the class of each 
character, then move it over to a .format function call argument.

     import string

     idchars = string.ascii_letters + string.digits + '_'  # + unicode letters
     capture = None
     isid = None
     fstring = '{a[2:3]:20d}'
     #~ fstring = '{a.foo}'

     identifier = []
     fmt_spec = []

     for char in fstring:
         print(char + ', ', end='')

         if char == '{':
             print('start_capture ', end='')
             capture = True
             isid = True
         elif char == '}':
             print('end_capture')
             capture = False
             break
         else:
             if capture:
                 if (char in idchars) and isid:
                     identifier.append(char)
                 else:
                     isid = False
                     fmt_spec.append(char)


     identifier = ''.join(identifier)
     fmt_spec = ''.join(fmt_spec)
     print()
     print('identifier:', repr(identifier))
     print('fmt_spec:  ', repr(fmt_spec))
     print('result:    ', "'{%s}'.format(%s)" % (fmt_spec, identifier))

And the results:

     >python3 fstr.py
     {, start_capture a, [, 2, :, 3, ], :, 2, 0, d, }, end_capture

     identifier: 'a'
     fmt_spec:   '[2:3]:20d'
     result:     '{[2:3]:20d}'.format(a)



On 08/04/2015 11:32 AM, Eric V. Smith wrote:
> Actually, a better link is:
> https://mail.python.org/pipermail/python-ideas/2015-July/034729.html
> where I discuss the pros and cons of str.format-like expressions, versus
> full expressions. Plus, Guido's response.



More information about the Python-ideas mailing list