Почему нельзя использовать обратную косую черту в f-строках?

В Python >=3.6, f-строки могут быть использованы в качестве замены str.format метод. В качестве простого примера, они эквивалентны:

'{} {}'.format(2+2, "hey")
f'{2+2} {"hey"}'

Не обращая внимания на спецификаторы формата, я могу переместить позиционные аргументы str.format внутри фигурных скобок. Обратите внимание, что мне разрешено просто поставить str литералы здесь, хотя это может показаться немного громоздким.

Однако есть некоторые ограничения. В частности, обратные слэши в любой форме или в любой форме запрещены внутри фигурных скобок:

'{}'.format("new\nline")  # legal
f'{"new\nline"}'          # illegal
f'{"\\"}'                 # illegal

Я даже не могу использовать \ разделить длинную линию, если она внутри скобок;

f'{2+\
2}'     # illegal

хотя это использование \ вполне допустимо в норме str"S;

'{\
}'.format(2+2)  # legal

Мне кажется, что жесткая остановка закодирована в парсере, если он видит \ символ вообще внутри фигурных скобок. Почему реализовано это ограничение? Хотя в документах указано это поведение, это не оправдывает причину.

4 ответа

Вы, кажется, ожидаете

'{}'.format("new\nline")

а также

f'{"new\nline"}'

быть эквивалентным. Это не то, чего я ожидал, и это не то, как обратная косая черта в f-строках работала в предыдущих версиях Python 3.6, где разрешалась обратная косая черта между фигурными скобками. Тогда вы получите ошибку, потому что

"new
line"

не является допустимым выражением Python.

Как только что продемонстрировано, обратные слеши в скобках сбивают с толку и неоднозначны, и они были запрещены, чтобы избежать путаницы:

Смысл этого в том, чтобы запретить запутанный код, такой как:

>>> d = {'a': 4}
>>> f'{d[\'a\']}'
'4'

Кроме того, я не разрешу использовать экранирование для скобок, как в:

>>> f'\x7bd["a"]}'
'4'

(где chr(0x7b) == "{").

Досадно, что этого нельзя сделать:

      things = ['Thing one','Thing two','Thing three']
print(f"I have a list of things: \n{'\n'.join(things)}")

Но можно и так:

      things = ['Thing one','Thing two','Thing three']
nl = '\n'
print(f"I have a list of things:\n{nl.join(things)}")

Для новых строк вы можете использовать os.linesep вместо \n. Например:

      >>> import os
>>> 
>>> print(f"Numbers:\n{os.linesep.join(map(str, [10, 20, 30]))}")
Numbers:
10
20
30

Я не уверен, поможет ли это, но вместо незаконного

      f'{"new\nline"}'

можно было бы использовать

      f'{"new"+chr(10)+"line"}'
Другие вопросы по тегам