Logo Questions Linux Laravel Mysql Ubuntu Git Menu

Why don't f-strings play nicely with dictionaries?

f-strings don't behave nicely when used with dictionaries, as mentioned here.

Here is an example of the not-so-nice behavior:

d = {'foo': 'bar'}

# Both work as expected

# This only works when different quotations are used in the inner and outer strings

# This doesn't work

# The .format() method doesn't care

The last two f-strings listed result in a SyntaxError: invalid syntax, which happens because the string '{d['foo']}' is evaluated as '{d['foo']}'.

What is the underlying reason everything inside the curly brackets of f-strings doesn't get evaluated separately, as when using the old .format() method, and what could possibly be the reason for implementing f-strings in this way?

I love f-strings, but this seems like a point in favor of the old method.

like image 637
OfficialThrowaway Avatar asked Mar 05 '23 07:03


1 Answers

F-strings are literal strings. Including unescaped quotes within quotes (of the same type) is invalid syntax. This makes sense, since the result is ambiguous: the interpreter will not know when the string should end. One traditional way of including quotes within quotes is to use a backslash. But PEP498 forbids backslashes in expressions within f-strings:

Backslashes may not appear inside the expression portions of f-strings...You can use a different type of quote inside the expression...

Therefore, the only way left to access a dictionary value given a key in an f-string expression is to use a different type quote. Using single quotes, or double quotes, everywhere is ambiguous and gives SyntaxError.

str.format is a regular method, and as such works differently: d['foo'] is evaluated before the string is constructed. Just like when you feed arguments to a function, the arguments are evaluated before the function does anything.

like image 74
jpp Avatar answered Mar 17 '23 13:03