Trilhas
/
Python
Python
/
Programa
/
Formatação de strings
Fo

Formatação de strings em Python

1 exercício

Sobre Formatação de strings

Formatação de strings em Python

A formatação de strings é o processo de converter valores em strings e inseri-los em um modelo de string. O Zen do Python afirma que deve haver "uma forma óbvia de fazer algo em Python". Mas, quando o assunto é formatação de strings, as coisas são um pouco... menos zen.

Pode ser surpreendente descobrir que existem quatro formas principais de fazer formatação de strings em Python, cada uma para um cenário diferente. Parte disso se deve à longa história do Python, e parte a considerações como internacionalização ou sanitização de entradas. Vamos começar pelas adições mais recentes à caixa de ferramentas de formatação de strings e ir voltando até a formatação "old style" ou "no estilo printf()".

interpolação literal de strings: a f-string

Introduzidas no Python 3.6, as f-strings (abreviação de "formatted strings") ou a interpolação literal de strings são uma forma de avaliar (e formatar) expressões e strings de maneira rápida e eficiente para o tipo str, usando o prefixo f (ou F) antes das aspas (assim: f'{object}').

As f-strings podem ser usadas com todos os tipos de delimitadores de string, como os de uma linha (' ou ") e os de várias linhas (''' ou """). Quaisquer variáveis, expressões ou outros tipos colocados dentro das {} são primeiro avaliados, depois convertidos para str e, por fim, concatenados com os strs que estiverem fora das chaves.

Neste exemplo, inserimos dois valores de variáveis em uma frase (um str e um float):

>>> name = 'eighth'
>>> value = 1/8

# The f-string, using the two values.
# The .2f format code truncates, so the value displays as 0.12.
>>> f'An {name} is approximately {value:.2f}.'
'An eighth is approximately 0.12.'

As expressões avaliadas podem ser quase qualquer coisa. Algumas das (amplas) possibilidades que podem ser avaliadas: strs, números, variáveis, expressões aritméticas, expressões condicionais, tipos embutidos, slices, funções, lambdas, compreensões ou quaisquer objetos com os métodos __str__ ou __repr__ definidos.

Do simples ao complexo:

Inserindo uma variável: o uso mais simples de uma f-string é colocar uma variável diretamente na string.

# Assigning a variable.
>>> name = "World"

# Inserting that variable.
>>> f'Hello, {name}!'
'Hello, World!'

Expressões dentro de {}: qualquer expressão Python válida pode ser avaliada dentro das chaves. Repare que usar aspas duplas dentro de uma f-string delimitada por aspas simples (ou vice-versa) evita a necessidade de sequências de escape:

# A dictionary of key:value pairs.
>>> waves = {'water': 1, 'light': 3, 'sound': 5}

# Inserting the whole dict.
>>> f'Wave ranks: {waves}'
"Wave ranks: {'water': 1, 'light': 3, 'sound': 5}"

# An expression can be evaluated inline:
>>> f"Tenfold the value of 'light' is {waves['light'] * 10}."
"Tenfold the value of 'light' is 30."

# A method call can also be evaluated inline:
>>> f'{"hello world!".title()} is a classic greeting.'
'Hello World! is a classic greeting.'

# An f-string can be nested inside another f-string:
>>> f"{f'hello world!'.title()} is a classic greeting."
'Hello World! is a classic greeting.'

Formatação de saída: a mini-linguagem de especificação de formato pode ser usada para controlar alinhamento, precisão numérica e muito mais. A especificação de formato vem depois do valor, separada por um :.

# Right-align a value to ten characters, and round it to 3 decimal places.
>>> value = 1 / 7
>>> f'One seventh is {value:10.3f}.'
'One seventh is      0.143.'

# A format specification can be set using variables as well.
>>> padding = 10
>>> precision = 3
>>> f'One seventh is {value:{padding}.{precision}f}.'
'One seventh is      0.143.'

Juntando tudo: variáveis, expressões, chamadas de função e formatação de saída:

>>> precision = 3
>>> f"{30e8 * 111_000:6.{precision}e}"
'3.330e+14'

>>> verb = 'meet'
>>> the_end = ['end', 'of', 'transmission']
>>> f'"Have a {"NICE".lower()} day, I will {verb} you after {30e8 * 111_000:6.{precision}e} light-years."{the_end}'
'"Have a nice day, I will meet you after 3.330e+14 light-years."[\'end\', \'of\', \'transmission\']'

# Did you notice the escaped single-quotes in the previous example?
# Using double quotes instead of single quotes for the f-string means the list's single-quoted strings print cleanly.
>>> f"Have a nice day. {the_end}"
"Have a nice day. ['end', 'of', 'transmission']"

Há duas limitações principais que você precisa conhecer. As expressões dentro de uma f-string não podem ser vazias. Além disso, antes do Python 3.12, elas não podiam conter comentários.

>>> f"An empty expression will error: {}"
SyntaxError: f-string: empty expression not allowed

>>> word = 'word'
>>> f"""A comment in a triple quoted f-string: {
    word # I chose a nice variable
}"""
'A comment in a triple quoted f-string: word'
Caution

A interpolação de strings não pode ser usada junto com a API GNU gettext para internacionalização (I18N) e localização (L10N). Por isso, recomenda-se usar a classe string.Template ou o método str.format() descritos abaixo no lugar de uma f-string em qualquer cenário de tradução que envolva "encapsular strings".

Lembre-se também de que usar expressões dentro das chaves {} de uma f-string é parecido com usar eval() ou exec(), então não é muito seguro e nunca deve ser usado com dados fornecidos pelo usuário.

O método str.format()

O método str.format() substitui os espaços reservados dentro da string por valores passados como argumentos para a função. Os espaços reservados são identificados por nomes ({price}), por números ({0} ou índices) ou até por espaços reservados vazios (posicionais) {}.

Por exemplo:

# A named placeholder and a positional placeholder.
>>> 'My text: {placeholder_1} and {}.'.format(12, placeholder_1='named placeholder')
'My text: named placeholder and 12.'

Assim como as f-strings, o str.format() do Python oferece suporte a toda uma variedade de especificadores de formato da mini-linguagem, que podem ser usados para alinhar texto, truncar decimais e muito mais.

O padrão completo do especificador de formatação é {[<name>][!<conversion>][:<format_specifier>]}:

  • <name> pode ser um espaço reservado nomeado, um número ou vazio.
  • !<conversion> é opcional e deve ser uma destas três conversões: !s para str(), !r para repr() ou !a para ascii(). Por padrão, usa-se str().
  • :<format_specifier> é opcional e controla como o valor é exibido. Mais informações sobre as opções possíveis podem ser encontradas aqui.

Exemplo de conversões para uma letra com diacrítico:

# Fills in the object at index zero, converted to a string.
>>> 'An e with an umlaut: {0!s}'.format('ë')
'An e with an umlaut: ë'


# Fills in the object at index zero, converted to a repr.
>>> 'An e with an umlaut (object representation): {0!r}'.format('ë')
"An e with an umlaut (object representation): 'ë'"


# Fills in the object at index zero, converted to ASCII.
>>> 'An e with an umlaut converted into ASCII: {0!a}'.format('ë')
"An e with an umlaut converted into ASCII: '\xeb'"


# Fills in the object in the first position,
# then fills in the object in the second position formatted as a repr.
>>> 'She said her name is not {} but {!r}.'.format('Chloe', 'Zoë')
"She said her name is not Chloe but 'Zoë'."

Exemplos de especificadores de formato comuns:

# Integer and binary/hex representations of the same number.
>>> my_num = 42
>>> f"{my_num} in binary is {my_num:b}. In hex, it is {my_num:x}"
"42 in binary is 101010. In hex, it is 2a"

# Alignment: left (<), right (>), and center (^) using up to ten characters total.
>>> f"[{"left":<10}] [{"right":>10}] [{"center":^10}]"
"[left      ] [     right] [  center  ]"

# Float precision and scientific notation (up to three decimal places).
>>> pi = 3.141592653589793
>>> f"Fixed: {pi:.3}  Scientific: {pi:.3e}"
"Fixed: 3.142  Scientific: 3.142e+00"

# Thousands separator and percentage.
>>> balance = 1000
>>> rate = 0.0225
>>> f"Balance: ${balance:,.0f}  Interest rate: {rate:.1%}"
"Balance: $1,000  Interest rate: 2.2%"

# Putting it all together:
>>> items = [("Widget", 1250, 9.991), ("Gadget", 37, 24.503), ("Doohickey", 4, 149.002)]
>>> header = f"{"Item":<12} {"Qty":>6} {"Price":>9}"
>>> print(header)
Item            Qty     Price
>>> for name, qty, price in items:
...     print(f"{name:<12} {qty:>6} {price:>9.2f}")
Widget         1250      9.99
Gadget           37     24.50
Doohickey         4    149.00

Há mais exemplos no final desta documentação.

Formatação com %, ou formatação no estilo printf()

O uso do operador % para formatação é o método mais antigo de formatação de strings em Python. Ele vem da linguagem C e permite usar argumentos posicionais para construir uma str.

Esse método foi superado tanto pelas f-strings quanto pelo str.format(), e é por isso que a formatação com % recebeu o apelido de "Old Style". Ele ainda pode ser encontrado em Python 2 e/ou em código legado. Embora esse método funcione no Python 3.x, a formatação com % costuma ser evitada porque é propensa a erros, é menos eficiente, tem menos opções disponíveis e qualquer incompatibilidade entre espaço reservado e argumento pode gerar uma exceção. O uso do operador % é parecido com printf(), por isso às vezes também é chamado de formatação printf.

# Assigning a variable.
>>> name = "Anna-conda"

# Building a string using %.
>>> "The snake's name is %s." % name
"The snake's name is Anna-conda."

No exemplo acima, o operador % substitui o espaço reservado %s pela variável name em tempo de execução. Se você quiser adicionar várias variáveis a uma string, precisa fornecer uma tupla contendo um objeto para cada espaço reservado depois do %:

# Assigning variables.
>>> name = "Billy the Kid"
>>> fruit = "grapes"

# Building a string using %.
>>> "Surprisingly, %s's favorite snack was %s." %(name, fruit)
"Surprisingly, Billy the Kid's favorite snack was grapes."

Strings de modelo

O string.Template() (que não deve ser confundido com as t-strings do Python 3.14) é uma classe do módulo string (diferente do tipo str embutido), que faz parte da biblioteca padrão do Python, mas precisa ser importada para ser usada. As strings de modelo oferecem suporte a substituições baseadas em $ e são bem mais simples e menos capazes que as outras opções mencionadas aqui. No entanto, elas podem ser muito úteis para internacionalização complicada ou para sanitizar entradas externas.

O string.Template é considerado mais seguro para entradas de usuário não confiáveis, porque impede a avaliação de expressões arbitrárias ou o acesso a atributos de objetos, o que reduz os ataques de injeção de string de formato.

>>> from string import Template

>>> name = "Anna-Conda"

# Creating a Template with placeholder text.
>>> template_string = Template("The snake called `$snake_name` has escaped!")

# Calling .substitute() to replace the placeholder with a value.
>>> template_string.substitute(snake_name=name)
'The snake called `Anna-Conda` has escaped!'

Você encontra mais informações sobre string.Template na documentação do Python.

Como escolher qual método de formatação usar?

Com todas essas opções e mini-linguagens, como decidir o que usar na hora de formatar strings em Python? Aqui vão algumas orientações rápidas:

  1. As f-strings são as mais novas e as mais fáceis de ler. Se você não precisa internacionalizar, elas devem ser o método preferido no Python 3.6+.

  2. O str.format() é versátil, poderoso e compatível tanto com o gnu gettext quanto com a maioria das versões do Python.

  3. Se o que você precisa é de simplicidade, segurança e/ou muita internacionalização, o string.Template() pode ser usado para reduzir riscos quando entradas de usuários precisam ser tratadas e para encapsular strings de tradução.

  4. O operador % é geralmente considerado obsoleto para código novo, embora ainda funcione no Python moderno. Ele deve ser usado principalmente para compatibilidade com bases de código mais antigas. A formatação com % é mais propensa a erros (e tem menos recursos) que os outros métodos, e pode causar problemas na exibição de caracteres não ASCII. Consulte a sua distribuição específica do Python para saber detalhes de suporte, caso pretenda usá-lo.

Se você quiser ir além, tudo sobre formatação e boas práticas de formatação de strings em Python são bons pontos de partida.

Editar via GitHub O link abre em uma nova janela ou aba