Рассмотрим следующий код Python, использующий библиотеку регулярных выражений re.
import re
re.compile(rf"{''.join(['{c}\\s*' for c in 'qqqq'])}")
Я запускал его в двух разных REPL:
https://www.pythonmorsels.com/repl/
https://www.online-python.com/#google_vignette
Первый из которых не выдает ошибки, а второй выдает следующую ошибку:
File "main.py", line 2
re.compile(rf"{''.join(['{c}\\s*' for c in 'qqqq'])}")
^
SyntaxError: f-string expression part cannot include a backslash
Я хотел бы понять, почему иногда я получаю сообщение об ошибке, а не другие. Как я могу сузить именно то, в чем заключается разница?
«Это из-за другой версии Python?» — спрашиваете вы, не удосужившись сообщить о версиях Python на машине вашего друга и на вашей.
@Kaz, спасибо, что указали на путаницу. Я упростил вопрос, сосредоточив внимание только на ответах. Пожалуйста, учтите это изменение.
@Mike'Pomax'Kamermans, согласен, это странная вещь, я не планирую использовать этот код, меня просто интересует тот факт, что есть разница в поведении одного репла и другого
Я не говорю, что это «странная вещь», я указываю на то, что это «невозможно сделать»: что-то не может быть «сырой и не сырой» строкой одновременно. Понимание того, почему два сервиса по-разному справляются с полной ерундой, нас ничему не учит. Если вам действительно интересно, вам следует посмотреть, что говорит Python, а затем связаться с сопровождающими службы, которая не генерирует правильный результат, чтобы они могли исправить свой веб-сайт.
@Mike'Pomax'Kamermans Строки в «необработанном формате» имеют смысл, «необработанная» часть означает, что не интерпретируются символы обратной косой черты в строковой части, «отформатированный» означает, что существуют интерполированные выражения. Однажды я использовал строку «rf» для построения регулярного выражения (пожалуйста, не распинайте меня за часть регулярных выражений, я был молод и неопытен)
Обойти проблему можно с помощью:
import re
re.compile("{0}".format(''.join([fr'{c}\s*' for c in 'qqqq'])))
Это работает для обоих предоставленных вами ответов. Он отправляет 'q\s*q\s*q\s*q\s*' для повторной компиляции.
Я предполагаю, что «\\s» предназначалось для сокращения до «\s».
Второй, выдающий синтаксическую ошибку, использует Python 3.8.5, который был до того, как в Python был добавлен PEP 701. PEP 701 наконец-то добавил f-строки в парсер Python 3.12, чтобы они могли содержать любое допустимое выражение, включающее строки с обратной косой чертой. Python до версии 3.12 постобрабатывает f-строки с помощью странного специального анализатора, который действительно сбивается с толку, когда видит обратную реакцию внутри части выражения.
Первый онлайн-REPL, который не выдает ошибок, работает под управлением Python 3.12.0.
Теперь попробуйте сам Python? А затем быстро подумайте над тем, что вы написали:
rf
не имеет смысла, потому чтоr
означает «необработанная строка», т. е. все внутри разделителей буквально то, что есть, нет никакого скрытого значения, замен, экранирования и т. д., тогда какf
означает «отформатированное». строка», где{...}
делает прямо противоположное тому, что, по утверждениюr
, должно произойти. Но что еще более любопытно: вашjoin
уже формирует соответствующим образом определенную строку, зачем вам тогда заключать ее в пустую строку? Просто скажитеre.compile(''.join(['{c}\\s*' for c in 'qqqq']))
, готово.