3.1. Syntax T-String
New string literal prefix:
t'...'Stands for Template String
Similar to f-strings (formatted string literals)
Uses
string.templatelibmoduleSince Python 3.14
3.1.1. Recap
value- the value of the expressionexpression- text found inside the curly brackets ({and}), including any whitespace, excluding the curly brackets themselves, and ending before the first!,:, or=if any is presentconversion-a,r,sorNone, depending on whether a conversion flag was present, ie."Hello {user!r}"format_spec- the format specifier, ie."Hello {value:.2f}"or"Hello {value:myfspec}"
>>> a = 1
>>> b = 2
Expression (a+b):
>>> f'Result is {a+b}'
'Result is 3'
Conversion (!s or !r or !a):
>>> f'Result is {a+b!s}'
'Result is 3'
>>>
>>> f'Result is {a+b!r}'
'Result is 3'
>>>
>>> f'Result is {a+b!a}'
'Result is 3'
Format Specifier (.2f):
>>> f'Result is {a+b:.2f}'
'Result is 3.00'
3.1.2. Problem
The following code constructs a SQL query using f-strings
However, it does not provide a way to analyze the structure of the query
It poses security risks (SQL injection) if user inputs are not sanitized
Non symptomatic example:
>>> def execute(query):
... print(query)
>>>
>>>
>>> username = 'alice'
>>> password = 'secret'
>>>
>>> execute(f'SELECT * FROM users WHERE username="{username}" AND password="{password}"')
SELECT * FROM users WHERE username="alice" AND password="secret"
Problematic example (SQL injection):
>>> def execute(query):
... print(query)
>>>
>>>
>>> username = '" OR 1==1; --'
>>> password = 'secret'
>>>
>>> execute(f'SELECT * FROM users WHERE username="{username}" AND password="{password}"')
SELECT * FROM users WHERE username="" OR 1==1; --" AND password="secret"
3.1.3. Solution
Use t-strings to create a template representation of the SQL query
This allows for safer handling and analysis of the query structure
>>> def execute(query):
... print(query)
>>>
>>>
>>> username = 'alice'
>>> password = 'secret'
>>>
>>> execute(t'SELECT * FROM users WHERE username="{username}" AND password="{password}"')
Template(strings=('SELECT * FROM users WHERE username="', '" AND password="', '"'),
interpolations=(Interpolation('alice', 'username', None, ''),
Interpolation('secret', 'password', None, '')))
3.1.4. Rationale
>>> from string.templatelib import Interpolation, Template
>>>
>>>
>>> def execute(tstring):
... if not isinstance(tstring, Template):
... raise TypeError('t-string expected')
... result = []
... for part in tstring:
... if isinstance(part, str):
... result.append(part)
... if isinstance(part, Interpolation):
... v = part.value
... e = part.expression
... c = part.conversion
... f = part.format_spec
... # ... <your code here> ...
... iterpolated = format(v, f)
... result.append(iterpolated)
... return ''.join(result)
3.1.5. Use Case - 1
>>> from string.templatelib import Interpolation
>>>
>>>
>>> def debug(tstring):
... for part in tstring:
... if isinstance(part, Interpolation):
... v = part.value
... e = part.expression
... c = part.conversion
... f = part.format_spec
... print(f'{v=}\n{e=}\n{c=}\n{f=}')
>>>
>>>
>>> a = 1
>>> b = 2
>>> debug(t'Hello {a+b}')
v=3
e='a+b'
c=None
f=''
>>> debug(t'Hello {a+b!s}')
v=3
e='a+b'
c='s'
f=''
>>> debug(t'Hello {a+b:.2f}')
v=3
e='a+b'
c=None
f='.2f'
>>> debug(t'Hello {a+b=}')
v=3
e='a+b'
c='r'
f=''
3.1.6. Further Reading
3.1.7. Assignments
# %% About
# - Name: Syntax T-String Usage
# - Difficulty: easy
# - Lines: 1
# - Minutes: 2
# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author
# %% English
# 1. Create t-string with text 'Hello Alice' using variable `NAME`
# 2. Define variable `result` with the solution
# 3. Run doctests - all must succeed
# %% Polish
# 1. Stwórz t-string z tekstem 'Hello Alice' używając zmiennej `NAME`
# 2. Zdefiniuj zmienną `result` z rozwiązaniem
# 3. Uruchom doctesty - wszystkie muszą się powieść
# %% Expected
# >>> print(result)
# Template(strings=('Hello ', ''), interpolations=(Interpolation('Alice', 'NAME', None, ''),))
# %% Doctests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 14), \
'Python has an is invalid version; expected: `3.14` or newer.'
>>> assert 'result' in globals(), \
'Variable `result` is not defined; assign result of your program to it.'
>>> assert result is not Ellipsis, \
'Variable `result` has an invalid value; assign result of your program to it.'
>>> assert type(result) is Template, \
'Variable `result` has an invalid type; expected: `Template`.'
>>> assert 'Hello ' in result.strings, \
'Word `Hello` must be in the `result`'
>>> assert result.interpolations, \
'Variable `result.interpolations` has invalid value; expected not empty.'
>>> result
Template(strings=('Hello ', ''), interpolations=(Interpolation('Alice', 'NAME', None, ''),))
"""
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -f -v myfile.py`
# %% Imports
# %% Types
from string.templatelib import Template, Interpolation
result: Template
# %% Data
NAME = 'Alice'
# %% Result
result = ...
# %% About
# - Name: Syntax T-String Validation
# - Difficulty: easy
# - Lines: 1
# - Minutes: 2
# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author
# %% English
# 1. Create function `result` that checks if argument is a t-string Template
# 2. If not, raise `TypeError` with message 'Expected a Template instance'
# 3. If yes, return `True`
# 4. Run doctests - all must succeed
# %% Polish
# 1. Stwórz funkcję `result`, która sprawdza czy argument jest t-stringowym Template
# 2. Jeśli nie, rzuć `TypeError` z komunikatem 'Expected
# 3. Jeśli tak, zwróć `True`
# 4. Uruchom doctesty - wszystkie muszą się powieść
# %% Expected
# >>> result(t'Hello')
# True
#
# >>> result('Hello')
# Traceback (most recent call last):
# TypeError: Expected a Template instance
#
# >>> result(f'Hello')
# Traceback (most recent call last):
# TypeError: Expected a Template instance
#
# >>> result(r'Hello')
# Traceback (most recent call last):
# TypeError: Expected a Template instance
# %% Doctests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 14), \
'Python has an is invalid version; expected: `3.14` or newer.'
>>> assert 'result' in globals(), \
'Function `result` is not defined; assign result of your program to it.'
>>> assert result is not Ellipsis, \
'Function `result` has an invalid value; assign result of your program to it.'
>>> assert callable(result), \
'Function `result` has an invalid type; expected: `callable`.'
>>> result(t'Hello')
True
>>> result('Hello')
Traceback (most recent call last):
TypeError: Expected a Template instance
>>> result(f'Hello')
Traceback (most recent call last):
TypeError: Expected a Template instance
>>> result(r'Hello')
Traceback (most recent call last):
TypeError: Expected a Template instance
"""
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -f -v myfile.py`
# %% Imports
# %% Types
from string.templatelib import Template
from typing import Callable
result: Callable[[Template|str], None|bool]
# %% Data
# %% Result
def result(x):
...