[Python-Dev] PEP-498: Literal String Formatting

MRAB python at mrabarnett.plus.com
Mon Aug 10 21:57:02 CEST 2015


On 2015-08-10 20:23, Guido van Rossum wrote:
> On Mon, Aug 10, 2015 at 8:49 PM, Eric V. Smith <eric at trueblade.com
> <mailto:eric at trueblade.com>> wrote:
>
>     On 08/10/2015 02:44 PM, Yury Selivanov wrote:
>     > On 2015-08-10 2:37 PM, Eric V. Smith wrote:
>     >> This is why I think PEP-498 isn't the solution for i18n. I'd really like
>     >> to be able to say, in a debugging context:
>     >>
>     >> print('a:{self.a} b:{self.b} c:{self.c} d:{self.d}')
>     >>
>     >> without having to create locals to hold these 4 values.
>     >
>     > Why can't we restrict expressions in f-strings to
>     > attribute/item getters?
>     >
>     > I.e. allow f'{foo.bar.baz}' and f'{self.foo["bar"]}' but
>     > disallow f'{foo.bar(baz=something)}'
>
>     It's possible. But my point is that Barry doesn't even want
>     attribute/item getters for an i18n solution, and I'm not willing to
>     restrict it that much.
>
>
> I also don't want to tie this closely to i18n. That is (still) very much
> a wold of its own.
>
> What I want with f-strings (by any name) is a way to generalize from
> print() calls with multiple arguments. We can write
>
>    print('Todo:', len(self.todo), '; busy:', len(self.busy))
>
> but the same thing is more awkward when you have to pass it as a single
> string to a function that just sends one string somewhere. And note that
> the above example inserts a space before the ';' which I don't really
> like. So it would be nice if instead we could write
>
>    print(f'Todo: {len(self.todo)}; busy: {len(self.busy)}')
>
> which IMO is just as readable as the multi-arg print() call[1], and
> generalizes to other functions besides print().
>
> In fact, the latter form has less punctuation noise than the former --
> every time you insert an expression in a print() call, you have a
> quote+comma before it and a comma+quote after it, compared to a brace
> before and one after in the new form. (Note that this is an argument for
> using f'{...}' rather than '\{...}' -- for a single interpolation it's
> the same amount of typing, but for multiple interpolations,
> f'{...}{...}' is actually shorter than '\{...}\{...}', and also the \{
> part is ugly.)
>
> Anyway, this generalization from print() is why I want arbitrary
> expressions. Wouldn't it be silly if we introduced print() today and
> said "we don't really like to encourage printing complicated
> expressions, but maybe we can introduce them in a future version"... :-)
>
> Continuing the print()-generalization theme, if things become too long
> to fit on a line we can write
>
>    print('Todo:', len(self.todo),
>          '; busy:', len(self.busy))
>
> Can we allow the same in f-strings? E.g.
>
>    print(f'Todo: {len(self.todo)
>          }; busy: {len(self.busy)
>          }')
>
> or is that too ugly? It could also be solved using implicit
> concatenation, e.g.
>
>    print(f'Todo: {len(self.todo)}; '
>          f'busy: {len(self.busy)}')
>
> [1] Assuming syntax colorizers catch on.
>
I'd expect f'...' to follow similar rules to '...'.

You could escape it:

print(f'Todo: {len(self.todo)\
         }; busy: {len(self.busy)\
         }')

which would be equivalent to:

print(f'Todo: {len(self.todo)        }; busy: {len(self.busy)        }')

or use triple-quoted a f-string:

print(f'''Todo: {len(self.todo)
         }; busy: {len(self.busy)
         }''')

which would be equivalent to:

print(f'Todo: {len(self.todo)\n        }; busy: {len(self.busy)\n        }')

(I think it might be OK to have a newline in the expression because
it's wrapped in {...}.)



More information about the Python-Dev mailing list