Python f-strings provide immediate string interpolation for everyday use, while t-strings (Python 3.14+, PEP 750) create structured Template objects ideal for safe, customizable rendering in scenarios like HTML or logging.

Core Differences

F-strings eagerly evaluate {} expressions into a final str, losing all template structure. T-strings preserve segments and interpolations as an iterable Template, allowing renderers to process values securely without direct concatenation.

Basic Example with Iteration:

name = "Alice"
age = 30

f_result = f"Hello, {name}! You are {age} years old."
print(f_result)  # Hello, Alice! You are 30 years old.
print(type(f_result))  # <class 'str'>

t_result = t"Hello, {name}! You are {age} years old."
print(type(t_result))  # <class 'string.templatelib.Template'>
print(list(t_result))  # ['Hello, ', Interpolation('Alice', 'name', None, ''), '! You are ', Interpolation(30, 'age', None, ''), ' years old.']

T-strings expose components for targeted processing.

Syntax and Formatting

Format specifiers work in both, but t-strings defer final application.

Formatting Example:

pi = 3.14159

f_pi = f"Pi ≈ {pi:.2f}"
print(f_pi)  # Pi ≈ 3.14

t_pi = t"Pi ≈ {pi:.2f}"
result = ""
for i, s in enumerate(t_pi.strings):
    result += s
    if i < len(t_pi.interpolations):
        interp = t_pi.interpolations[i]
        if interp.format_spec:
            result += format(interp.value, interp.format_spec)
        else:
            result += str(interp.value)
print(result)  # Pi ≈ 3.14

Consumers can override or enhance formatting in t-strings.

HTML Rendering Example

T-strings prevent XSS by enabling per-value escaping.

Safe HTML Generation:

user_name = "<script>alert('XSS')</script>"
greeting = "Welcome"

html_tmpl = t"""
<html>
  <h1>{greeting}</h1>
  <p>Hello, {user_name}!</p>
</html>
"""

# Custom HTML renderer (no external libs needed)
def html_render(template):
    parts = []
    for segment in template:
        if isinstance(segment, str):
            parts.append(segment)
        else:
            # Simulate HTML escaping
            escaped = str(segment.value).replace('&', '&').replace('<', '<').replace('>', '>').replace("'", '&#x27;')
            parts.append(escaped)
    return ''.join(parts)

safe_html = html_render(html_tmpl)
print(safe_html)  
# <html>\n  <h1>Welcome</h1>\n  <p>Hello, <script>alert(&#x27;XSS&#x27;)</script>!</p>\n</html>

This shows t-strings' strength: structure enables selective escaping.

Logging Renderer Example

Safe Logging with Context:

import datetime
timestamp = datetime.datetime.now()

user_id = "user123"
level = "ERROR"

log_tmpl = t"[{level}] User {user_id} logged in at {timestamp:%Y-%m-%d %H:%M:%S}"

def log_render(template):
    parts = []
    for segment in template:
        if isinstance(segment, str):
            parts.append(segment)
        else:
            parts.append(str(segment.value))  # Log-safe formatting
    return ''.join(parts)

log_entry = log_render(log_tmpl)
print(log_entry)  # [ERROR] User user123 logged in at 2026-01-11 13:35:00

T-strings keep logs structured yet safe.

Practical Use Cases Table

Scenario F-String Approach T-String + Render Benefit
Debug Logging f"{var=}" → instant string Custom formatters per field
HTML Generation Manual escaping everywhere Auto-escape via renderer
Config Templates Direct substitution Validate/transform values before render
CLI Output Simple trusted data Colorize/structure fields selectively

T-strings complement f-strings by enabling secure, modular rendering without sacrificing Python's concise syntax.