Python 3.14 представляет мощную новую функцию: шаблонные строки (template strings), формализованные в PEP 750. В то время как f-строки (f"") предлагают удобную встроенную интерполяцию, они сразу же преобразуются в обычные строки, что делает невозможным извлечение метаданных, управление поведением рендеринга или проверку того, какие выражения были интерполированы.
Шаблонные строки (t"") решают эту проблему, создавая структурированный объект (Template) вместо строки. Это дает разработчикам программный доступ к:
- Исходному выражению (
{username}) - Его вычисленному значению (
'abhimanyu') - Параметрам форматирования (
:.2f,!rи т.д.)
Результат: основа для создания более безопасной, проверяемой и повторно используемой обработки строк, особенно полезная для логирования, систем шаблонизации, веб-вывода и структурированных конвейеров.
Почему бы не использовать просто f-строки?
Многие случаи использования (HTML, shell-команды, логи) кажутся выполнимыми с помощью f-строк. Так почему же стоит переключиться?
Потому что t-строки это:
f-строки дают вам результат. t-строки дают вам контроль.
Начало работы
Перед погружением в реальные примеры использования, вот как работает базовая t-строка:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
from string.templatelib import Template user = "abhimanyu" template = t"Hello, {user}" print(template.strings) # Вывод: ('Hello, ', '') print(template.interpolations[0].expression) # Вывод: 'user' print(template.interpolations[0].value) # Вывод: 'abhimanyu' |
Вместо прямого преобразования в "Hello, abhimanyu", шаблон дает вам структурированный доступ к:
- Фрагментам строки (
"Hello, ") - Интерполированной переменной (
user) - Её текущему значению (
'abhimanyu')
Пример 1: Санитизация пользовательского ввода в shell-командах
При динамическом создании shell-команд (например, в сценариях автоматизации) прямая вставка пользовательского ввода с использованием f-строк может привести к инъекциям или нарушению кавычек:
|
1 |
command = f'ls "{path}"' # f-строка преобразуется немедленно — нет возможности проверить `path` позже |
Решение:
Используйте t-строку для отложенного рендеринга и санитизации входных значений перед окончательным построением:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
from string.templatelib import Template, Interpolation def build_command(template: Template) -> str: def sanitize(val): return str(val).replace('"', '\\"') # простой escape кавычек return "".join( sanitize(item.value) if isinstance(item, Interpolation) else item for item in template ) command = "ls" path = "/var/www" print(build_command(t'{command} "{path}"')) |
Вывод:
|
1 |
ls "/var/www" |
- С шаблонными строками значения всё ещё разделены в момент рендеринга, что позволяет выполнять безопасную предварительную обработку.
Пример 2: Структурированное логирование с встроенным контекстом
Традиционные строки логов смешивают человекочитаемый и машиночитаемый вывод, что затрудняет извлечение полей для анализа:
|
1 2 |
# f-строка: Невозможно чисто извлечь пары ключ-значение logline = f"User {user} did {action}" |
Решение:
Шаблонные строки позволяют получить прямой доступ ко всем интерполированным значениям и использовать их для создания структурированных логов:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
import json from string.templatelib import Template, Interpolation class DebugLog: def __init__(self, template: Template): self.template = template def __str__(self): message = "".join( str(item.value) if isinstance(item, Interpolation) else item for item in self.template ) fields = { item.expression: item.value for item in self.template if isinstance(item, Interpolation) } return f"{message} | {json.dumps(fields)}" action = "deploy" env = "staging" version = "v2.3.1" log = DebugLog(t"Action: {action}, Environment: {env}, Version: {version}") print(log) |
Вывод:
|
1 |
Action: deploy, Environment: staging, Version: v2.3.1 | {"action": "deploy", "env": "staging", "version": "v2.3.1"} |
- Это значительно упрощает парсинг логов, настройку оповещений и создание дашбордов — не требуется дополнительный парсинг или дублирование данных.
Пример 3: Рендеринг безопасного HTML-контента
Отображение пользовательского ввода в HTML (например, в панелях администратора, отчетах) может нарушить макет или, что еще хуже, внедрить вредоносный контент.
|
1 2 |
# Опасно, если ввод не обработан f"<div>{user_input}</div>" |
Решение:
Обработка интерполированных значений перед рендерингом:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
def safe_html(template: Template) -> str: def escape(val): return str(val).replace("<", "<").replace(">", ">") return "".join( escape(item.value) if isinstance(item, Interpolation) else item for item in template ) user_input = "<script>alert(1)</script>" print(safe_html(t"<div>{user_input}</div>")) |
Вывод:
|
1 |
<div><script>alert(1)</script></div> |
Теперь у вас есть полный контроль над тем, как и когда происходит санитизация, без изменения входных данных или их источника.
Пример 4: Кастомный рендер, эмулирующий f-строки
f-строки скрывают поведение форматирования внутренне. Нет возможности переопределить, как работают преобразования вроде !r, !s или :.2f.
Решение:
Создание пользовательского рендерера с использованием метаданных из каждой Interpolation:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
from typing import Literal from string.templatelib import Interpolation, Template def convert(value, conversion: Literal["a", "r", "s"] | None) -> str: return { "a": ascii, "r": repr, "s": str, None: lambda x: x }[conversion](value) def render(template: Template) -> str: parts = [] for item in template: if isinstance(item, str): parts.append(item) elif isinstance(item, Interpolation): val = convert(item.value, item.conversion) parts.append(format(val, item.format_spec)) return "".join(parts) name = "admin" score = 97.438 print(render(t"User: {name!r}, Score: {score:.1f}")) |
Вывод:
|
1 |
User: 'admin', Score: 97.4 |
Это позволяет реализовать поведение f-строк или расширить его в соответствии с вашей логикой форматирования или доменно-специфическими правилами.
Пример 5: Динамическое объединение шаблонов
Возможно, вы захотите создать полный шаблон, комбинируя более мелкие части, особенно в генераторах конфигураций, повторно используемых UI-компонентах или динамических конструкторах логов.
С f-строками это невозможно, так как они обрабатываются немедленно:
|
1 2 |
# f-строка: это не объединится как повторно используемые компоненты f"Stage: " + f"{env}" |
Решение:
Шаблонные строки позволяют выполнять композицию, Template + Template или Template + str возвращает новый объект Template:
|
1 2 3 4 5 6 7 8 9 10 |
from string.templatelib import Interpolation env = "prod" # Должно быть определено *до* t-строки t1 = t"Stage: " t2 = t"{env}" combined = t1 + t2 # Рендеринг результата print("".join(str(item.value if isinstance(item, Interpolation) else item) for item in combined)) |
Вывод:
|
1 |
Stage: prod |
⚠️ Важно: интерполяции вычисляются немедленно
Как и в случае с f-строками, t-строки вычисляют выражения в момент создания строки, а не при её рендеринге:
|
1 2 3 4 5 |
env = "staging" t = t"{env}" env = "prod" # Последующее изменение не влияет print(t.interpolations[0].value) |
Вывод:
|
1 |
staging |
Это означает:
- Всегда определяйте переменные до их использования внутри литерала
t"" - Шаблонные строки — это не ленивые шаблоны; это структурированные снимки выражений и их вычисленных значений
Используйте
t-строки, когда хотите комбинировать шаблоны, проверять значения или преобразовывать вывод.
Не ожидайте, что они будут повторно вычислять выражения во время рендеринга, они фиксируют состояние один раз, а не по запросу.
Заключительные мысли
Шаблонные строки в Python 3.14 — это не замена f-строкам, а их эволюция для более продвинутых и контролируемых сценариев использования.
Если f-строки отдают приоритет простоте и немедленному выводу, то t-строки фокусируются на структуре, безопасности и гибкости. Они позволяют проверять выражения, изменять поведение рендеринга, санитизировать значения на лету и повторно использовать шаблоны как объекты, а не статический текст.
Если вы работаете над:
- Фреймворками для логирования, которые извлекают значения полей
- Движками шаблонизации, где пользовательский ввод должен проходить валидацию
- DSL или инструментами автоматизации, которые создают команды или конфигурации
- Любой системой, где как строится строка имеет такое же значение, как и что она в итоге представляет
то t-строки — правильный инструмент для вас.
Используйте f-строки, когда всё, что вам нужно — это строка.
Используйте t-строки, когда вам нужен контроль до финализации строки.
Часто задаваемые вопросы
Что такое шаблонные строки (t»») в Python 3.14, и чем они отличаются от f-строк?
Шаблонные строки (t"") возвращают структурированный объект Template вместо обычной строки. В отличие от f-строк, которые сразу создают строку, t-строки дают доступ к метаданным интерполяции, таким как имена переменных, вычисленные значения и инструкции форматирования. Это позволяет выполнять интроспекцию, трансформацию и более безопасный рендеринг.
Когда следует использовать шаблонные строки вместо f-строк?
Используйте шаблонные строки, когда:
- Вам нужно санитизировать или проверять интерполированные значения
- Вы создаете структурированные логи, shell-команды или HTML безопасным способом
- Вы хотите отложить рендеринг или настроить поведение вывода
- Вы динамически составляете строки из более мелких частей
Используйте f-строки, когда вам нужен только немедленный вывод строки.
Вычисляются ли шаблонные строки лениво?
Нет. Как и f-строки, шаблонные строки немедленно вычисляют свои выражения в момент создания строки. Это означает, что все используемые переменные должны быть уже определены, а изменения переменных после создания t-строки не повлияют на сохраненные в шаблоне значения.
Можно ли создавать пользовательские рендереры с помощью шаблонных строк?
Да. Вы можете получить доступ к отдельным интерполяциям (их значениям, флагам преобразования и спецификаторам форматирования) и создать пользовательскую логику рендеринга. Это полезно для воспроизведения или расширения поведения f-строк, например, для переопределения того, как интерпретируются !r или :.2f.
Каковы практические случаи использования шаблонных строк в Python 3.14?
Основные случаи использования включают:
- Безопасная генерация shell-команд (с санитизацией ввода)
- Структурированное логирование (представление полей как данных, а не просто строк)
- HTML-шаблонизация с безопасным экранированием
- Пользовательские DSL или генераторы конфигураций
- Составные строковые шаблоны для повторного использования в различных системах

Являюсь администратором нескольких порталов по обучению языков программирования Python, Golang и Kotlin. В составе небольшой команды единомышленников, мы занимаемся популяризацией языков программирования на русскоязычную аудиторию. Большая часть статей была адаптирована нами на русский язык и распространяется бесплатно.
E-mail: vasile.buldumac@ati.utm.md
Образование
Universitatea Tehnică a Moldovei (utm.md)
- 2014 — 2018 Технический Университет Молдовы, ИТ-Инженер. Тема дипломной работы «Автоматизация покупки и продажи криптовалюты используя технический анализ»
- 2018 — 2020 Технический Университет Молдовы, Магистр, Магистерская диссертация «Идентификация человека в киберпространстве по фотографии лица»