PEP 750: t-строки в 3.14
Недавно ревьюил один интересный PR в CPython: в питон добавили еще один способ форматировать строки. Теперь – со специальным АПИ для внешних интеграций. Расскажу: как и зачем.
Основная причина: использовать f строки удобно, но нет никакого АПИ для перехвата момента "вставки" или интерполяции значений. Например, при форматировании html или sql – требуется специальным образом делать escape для значений. И раньше код вида f"{template}" представлял собой дыру в безопасности и потенциальное место для XSS.
string.templatelib.Template
Новый префикс t не будет создавать объект str, он будет создавать объект класса string.templatelib.Template:
>>> user = 'sobolevn' >>> template = t"Hi, {user}" >>> template Template(strings=('Hi, ', ''), interpolations=(Interpolation('sobolevn', 'user', None, ''),)) >>> from string.templatelib import Template >>> isinstance(template, Template) True
Обратите внимание, что при создании template – у нас не произошло форматирование сразу. Мы создали объект, у которого есть свойства strings и interpolations, из которых можно собрать финальную отформатированную строку.
Давайте посмотрим на примере. Допустим, мы хотим формировать URL из наших данных:
>>> domain = 'example.com' >>> query = 'python string formatting is too complex' >>> template = t'https://{domain}?q={query}'
И сам код логики форматирования, где мы будем вставлять значения разным способом. Если у нас шаблон query, то мы будем использовать quote_plus для его форматирования. Остальные значения – будем вставлять как есть:
>>> from string.templatelib import Template, Interpolation >>> from urllib.parse import quote_plus >>> def format_url(template: Template) -> str: ... parts = [] ... for part in template: ... match part: ... case str() as s: # regular string ... parts.append(s) ... case Interpolation(value, expression='query'): ... parts.append(quote_plus(value)) ... case Interpolation(value): ... parts.append(value) ... return ''.join(parts)
И вот результат:
>>> format_url(template) 'https://example.com?q=python+string+formatting+is+too+complex'
Только теперь наш Template был отформатирован. Нами. Ручками.
У нас есть полный контроль за процессом форматирования. Вот в чем суть данного ПЕПа.
Фичи одной строкой
Работает
=как обычно вfстроках:t'{user=}'Есть привычные определители формата:
!r,!s,.2f, тдt строки можно конкатенировать:
t'Hello' + t' , world!'иt'Hello, ' + 'world'Поддерживается режим raw строк:
rt"Hi \n!"
Как устроено внутри?
Интересные места имплементации:
Новые классы
TemplateиInterpolationнаписанные на CНовый байткод
BUILD_INTERPOLATIONиBUILD_TEMPLATE
>>> import dis >>> user = 'sobolevn' >>> dis.dis('t"Hi, {user}"') 0 RESUME 0 1 LOAD_CONST 2 (('Hi, ', '')) LOAD_NAME 0 (user) LOAD_CONST 1 ('user') BUILD_INTERPOLATION 2 BUILD_TUPLE 1 BUILD_TEMPLATE RETURN_VALUE
Обсуждение: как вам еще один способ форматирования строк?
Если понравилось – заходи в тг, где я рассказываю, как я делаю CPython.
