PEP 750 – Aprovação das strings de template (t-strings)
(peps.python.org)- A PEP 750 introduz no Python um novo literal de string: strings de template (
t"...") - É uma forma generalizada de f-string, que cria o tipo
Templatee permite processar previamente a combinação entre a string e os valores interpolados - Pode ser útil em templates web, verificações de segurança e DSLs (Domain-Specific Languages)
Relação com outras PEPs
- As f-strings foram introduzidas na PEP 498, e sua sintaxe foi expandida na PEP 701
- A PEP 501 propôs strings de template genéricas (
i-strings), mas ficou em espera - A atual PEP 750 é uma forma simplificada e generalizada da PEP 501, evoluindo a partir das ideias existentes
Motivação e necessidade
- As f-strings são simples, mas como não permitem pré-processar os valores interpolados, podem gerar problemas de segurança
- Há preocupação com vulnerabilidades como injeção de SQL e ataques XSS
- Com strings de template, é possível processar os valores interpolados antes e usá-los com segurança
Exemplo:
evil = "<script>alert('evil')</script>"template = t"<p>{evil}</p>"assert html(template) == "<p><script>alert('evil')</script></p>"
Especificação das strings de template
Literais de string de template
- Definidos com o prefixo
touT - Avaliados como o tipo
string.templatelib.Template - Suportam sintaxe semelhante à de f-strings, inclusive com aninhamento
- Podem ser combinados com o prefixo
r(rt,tr) - Não podem ser combinados com os prefixos
ueb - Não é permitido misturar f-strings e strings de template
Tipo Template
- É um tipo imutável e possui os seguintes atributos:
strings: tupla de fragmentos de stringinterpolations: tupla de objetos de valores interpoladosvalues: tupla com os valores interpolados__iter__(): iterador que retorna strings e valores interpolados em sequência
Tipo Interpolation
value: resultado avaliadoexpression: string da expressão interpolada originalconversion: forma de conversão (r,s,aou None)format_spec: string de formatação
Exemplo:
name = "World"template = t"Hello {name!r}"assert template.interpolations[0].conversion == "r"
Especificador de depuração =
t"{value=}"é interpretado comot"value={value!r}"- Os espaços também são preservados (
t"{value = }"→"value = {value!r}")
Concatenação de strings de template
- O operador
+permite combinarTemplatecomstr, eTemplatecomTemplate - O resultado da concatenação é sempre do tipo
Template - A concatenação implícita de strings (
t"Hello " t"World") também é possível
Como processar strings de template
Exemplo: função de transformação para minúsculas/maiúsculas
def lower_upper(template):parts = []for s in template:if isinstance(s, str): parts.append(s.lower())else: parts.append(str(s.value).upper())
return "".join(parts)
Exemplo: implementação com o mesmo processamento de f-string
- A função
f()pode gerar o mesmo resultado que uma f-string
Exemplo: logging estruturado
- Com strings de template, é possível emitir ao mesmo tempo a mensagem de log e os valores estruturados
- Pode ser implementado com
StructuredMessageou uma subclasse delogging.Formatter
Exemplo: processamento de template HTML
- A função
html()trata o conteúdo com escape adequado ou como atributo, dependendo da posição de inserção - Também há suporte a templates aninhados
Padrões avançados de uso
- Recomenda-se o uso de correspondência estrutural de padrões (instrução
match) - Strings estáticas podem ser usadas como chave de cache, permitindo memoização eficiente
- Também é possível analisar e processar via representações intermediárias, como AST
- Para avaliação Lazy ou Async, podem ser usados
lambdaeawait
Relação entre strings de template e strings de formatação existentes
- É possível definir funções de template de forma semelhante ao
.format()tradicional - Também é possível um
from_format()que analisa uma string externa e a converte emTemplate
Compatibilidade, segurança e aprendizado
- Em versões antigas do Python, a sintaxe pode gerar erro
- Em termos de segurança, o processamento por template aumenta a proteção
- A sintaxe, semelhante à de f-strings, facilita o aprendizado
Por que uma nova abordagem de templates?
- Templates existentes, como Jinja, costumam ser voltados para personalização ou para designers
- É necessário suporte no próprio Python para que desenvolvedores possam lidar diretamente com templates
- Isso permite aproveitar vantagens como expressividade e verificação de tipos
Resumo dos padrões de exemplo
- Correspondência estrutural de padrões e correspondência em atributos internos
- Reutilização de templates como se fossem funções
- Suporte a templates aninhados
- Suporte a avaliação Lazy/Async
- Otimização de cache com separação entre partes estáticas e dinâmicas
Outras considerações de design
- Templates não são convertidos em string, e
__str__()não é implementado - As classes relacionadas são fornecidas no módulo
string.templatelib TemplateeInterpolationsão comparados com base na identidade do objeto- As operações
==e<não são suportadas
Implementação de referência e exemplos
- Implementação no CPython
- Exemplos e testes disponíveis
Ideias rejeitadas
- Uso de prefixos arbitrários (
my_tag"...") - Avaliação adiada de todas as expressões interpoladas
- Implementação via protocolo
- Redefinição de
__eq__e__hash__ - Restauração completa da string original
- Adição do tipo
Decoded - Suporte a strings de template binárias
- Recurso para especificar o tipo de formato ("html", "sql" etc.)
- Limitação da concatenação de strings
- Permissão para conversores arbitrários (
!x)
3 comentários
A formatação mais satisfatória, para mim, só existe em JS e Python. Outras linguagens ficam meio...
Haverá uma maneira óbvia de fazer isso — e, de preferência, apenas uma.
Comentários no Hacker News
É interessante como diferentes linguagens lidam com formatação de strings
.format(), f-strings e t-stringsNick Humrich é um dos autores que reescreveram a PEP 501 para introduzir t-strings e está muito feliz com a aceitação desta PEP
Não há certeza de que um recurso no nível da linguagem tenha valor
Gosta de f-strings, mas há o problema de não ser possível adiar a avaliação
str.format, o que é incômodoComo mantenedor do lit-html, acha interessante a semelhança com template literals com tags do JavaScript
Templatedo Python separa a função tag e os argumentos é peculiar em relação ao JavaScripthtml()não seja necessáriaHá expectativa de que, assim como os template literals com tags do JavaScript ajudam com autoescape de HTML e parametrização de SQL, isso também seja aplicado ao Python
Há a opinião de que Python está se transformando em PHP
string.formato ideal, e%também é aceitável por ser usado há muito tempoReclamação sobre continuar adicionando coisas novas à linguagem
Há a opinião de que esta PEP é semelhante ao P1819 do C++
Há a opinião de que o código da PEP é excessivamente verboso