Template Strings — нові рядки-шаблони у Python 3.14

By Volodymyr Obrizan on Травень 15, 2025 · Прочитати цю публікацію іншими мовами: Russian English

У Python 3.14 зʼявилось нове розширення синтаксису мови — рядки-шаблони (template strings, t-strings, t-рядки). Розглянемо, що це таке, навіщо їх зробили та як з ними працювати.

Що таке Template Strings?

Рядки-шаблони (template strings, t-strings, t-рядки) — це узагальнення f-рядків, у яких замість префікса f використовується t. Замість того щоб обчислюватися як тип str, t-рядки обчислюються як екземпляр нового незмінного типу — Template (модуль string.templatelib).

Важливо: не треба плутати з Template Strings, які зʼявились у Python 2.4 ще у 2004 році (PEP 292) та виглядають ось так: s = Template('$who likes $what').

Розглянемо на прикладі де показана ця різниця між f-рядками та t-рядками:

name = "Volodymyr Obrizan"
f_string = f"Hello, {name}"
template = t"Hello, {name}"

print("f-string: ", f_string)
print("t-string: ", template)

Вивід на термінал:

f-string:  Hello, Volodymyr Obrizan
t-string:  Template(strings=('Hello, ', ''), interpolations=(Interpolation('Volodymyr Obrizan', 'name', None, ''),))

Зверніть увагу, що f-рядок f_string був обчислений одразу у рядок "Hello, Volodymyr Obrizan", а t-рядок template не був обчислений як рядок, а утворив обʼєкт типу Template. Таким чином, інтерполяція (перетворення шаблону) відбувається не миттєво, а відкладено.

Як обробляти такі шаблони?

Як обробляти такі шаблони щоб отримати конкретний рядок з вже підставленими значеннями? Алгоритм інтерполяції (перетворення) повинен визначити користувач.

Обʼєкт типу Template підтримує протокол __iter__, тобто можна отримати послідовно усі частини шаблону:

city = "Kharkiv"
weather = "20 C"
for item in t"Temperature in {city} is {weather}":
    print(item, type(item))

Вивід на термінал:

Temperature in  <class 'str'>
Interpolation('Kharkiv', 'city', None, '') <class 'string.templatelib.Interpolation'>
 is  <class 'str'>
Interpolation('20 C', 'weather', None, '') <class 'string.templatelib.Interpolation'>

Ми бачимо, що Template побудований з 4 частин:

  • "Temperature in " — рядок
  • {city} — обʼєкт типу Interpolation
  • " is " — рядок
  • {weather} — обʼєкт типу Interpolation

Використовуючі ітерацію по Template можна написати власний алгоритм інтерполяції таких шаблонів.

Приклад інтерполяції: secret_safe

Завдання: при виводі у лог-файли або на термінал бажано приховувати секрети: API-ключі, токени тощо.

Розробимо алгоритм інтерполяції шаблону secret_safe який повинен маскувати усі значення які передаються в шаблон. Для визначення чи є значення в шаблоні секретом будемо використовувати функцію shannon_entropy(data: str) -> float, яка обчислює ентропію алгоритмом Шеннона. Якщо ентропія для рядка перевищує певний поріг (у прикладі це 3,8) та довжина рядка більше 10 символів, то такий рядок будемо вважати секретом (функція is_probably_secret) та маскувати: заміняти середину секрета на зірочки: 123******890.

Функція secret_safe(template: Template) -> str обчислює шаблон у конкретний рядок.

import math
from collections import Counter
from string.templatelib import Interpolation, Template

# Обчислює ентропію Шеннона для заданого рядка
def shannon_entropy(data: str) -> float:
    return 0.0 if not data else -sum((count / len(data)) * math.log2(count / len(data)) for count in Counter(data).values())

# Перевіряє, чи рядок, ймовірно, є секретним (за довжиною та ентропією)
def is_probably_secret(s: str, threshold: float = 3.8) -> bool:
    return len(s) > 10 and shannon_entropy(s) > threshold

# Обробляє шаблон і маскує значення, які виглядають як секрети
def secret_safe(template: Template) -> str:
    parts: list[str] = []
    for item in template:
        # Перебираємо всі частини шаблону
        match item:
            # Якщо це звичайний текстовий фрагмент
            case str() as s:
                parts.append(s)
            # Якщо це інтерполяція змінної
            case Interpolation(value, _, _, _):
                # Якщо значення виглядає як секрет — маскуємо його
                if is_probably_secret(value):
                    parts.append(str(item.value)[:3] + "*****" + str(item.value)[-3:])
                else:
                    parts.append(str(item.value))

    # Об'єднуємо всі частини в один рядок
    return "".join(parts)

Приклад 1. Шаблон логіна та пароля:

login = "Volodymyr"
password = "aSalDsLOgrETAreFOLMA"

signup_template = t"Hi, {login}, your password is {password}."
print(secret_safe(signup_template))

Вивід на термінал:

Hi, Volodymyr, your password is aSa*****LMA.

Приклад 2. Шаблон для змінних оточення:

variables = {
    "AWS_REGION": "us-west-1",
    "AWS_OUTPUT_FORMAT": "json",
    "AWS_ACCESS_KEY_ID": "AKIAIOSFODNN7EXAMPLE",
    "AWS_SECRET_ACCESS_KEY": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
}

for k, v in variables.items():
    print(secret_safe(t"{k}={v}"))

Вивід на термінал:

AWS_REGION=us-west-1
AWS_OUTPUT_FORMAT=json
AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
AWS_SECRET_ACCESS_KEY=wJa*****KEY

Як попередні версії реагують на Template Strings?

Якщо спробувати використати синтаксис t-рядків у версія Python 3.13 та нижче, то інтерпретатор відреагують виключенням SyntaxError: invalid syntax:

  File "/Users/obrizan/Projects/Experiments/template-strings/main.py", line 3
    template = t"Hello, {name}"
                ^^^^^^^^^^^^^^^
SyntaxError: invalid syntax

Тому використовувати цей новий синтаксис треба обережно. Якщо потрібна сумісність з попередніми версіями Python (3.13 та нижче), то треба буде зачекати з використанням рядків-шаблонів.

Як встановити Python 3.14?

Python 3.14.0b1 — це перша публічна бета-версія інтерпретатора Python 3.14, яка вийшла 7 травня 2025. Перша бета — це важлива точка в розробці Python 3.14, тому що розробники не будуть додавати ніяких нових функцій, тільки виправлення помилок. Офіціальний реліз версії Python 3.14.0 заплановано на 7 жовтня 2025 року.

Рядки-шаблони доступні у Python 3.14, а як його встановити до офіційного виходу?

За допомогою пакетного менеджера uv

Встановлюємо пакетний менеджер uv: інструкції з інсталяції.

Перевіряємо, яка версії інтерпретатора Python доступні для встановлення. Для цього виконаємо команду uv python list в терміналі. Ця команда покаже, які версії Python вже встановлені та доступні для завантаження:

$ uv python list

cpython-3.14.0a6+freethreaded-macos-aarch64-none    <download available>
cpython-3.14.0a6-macos-aarch64-none                 <download available>
cpython-3.13.3-macos-aarch64-none                   /opt/homebrew/bin/python3.13
cpython-3.13.3-macos-aarch64-none                   /opt/homebrew/bin/python3
cpython-3.13.2+freethreaded-macos-aarch64-none      <download available>
cpython-3.13.2-macos-aarch64-none                   <download available>
cpython-3.13.1-macos-aarch64-none                   /usr/local/bin/python3.13 
cpython-3.13.1-macos-aarch64-none                   /Library/Frameworks/Python.framework/Versions/3.13/bin/python3.13
cpython-3.13.1-macos-aarch64-none                   /Library/Frameworks/Python.framework/Versions/3.13/bin/python3
...
<інші старі версії>

Під час написання цієї статті була доступна альфа-версія Python 3.14.0a6 з ідентифікатором cpython-3.14.0a6-macos-aarch64-none.

Завантажимо та встановимо цю версію виконавши команду uv python install cpython-3.14.0a6-macos-aarch64-none в терміналі:

$ uv python install cpython-3.14.0a6-macos-aarch64-none

Installed Python 3.14.0a6 in 2.59s
 + cpython-3.14.0a6-macos-aarch64-none

За допомогою інсталятора

Треба перейти на сторінку Current Pre-release Testing Versions, та знайти посилання на поточную бета-версію. Під час написання цієї статті була доступна бета-версія Python 3.14.0b1. Треба перейти на відповідну сторінку та в розділі Files обрати та завантажити інсталятор для вашої операційної системи:

Screenshot 2025-05-14 at 20.53.14.png

Після встановлення бета-версія Python 3.14 буде доступна за командою python3.14. Можна перевірити версію за допомогою команди в терміналі:

$ python3.14 --version

Python 3.14.0b1

Джерела

Telegram
Viber
LinkedIn
WhatsApp

Коментарі

Увійти щоб залишити коментар.

← Назад до блогу