Python f-strings: Formatando Textos

Na aula Juntar e Repetir Textos, montar a frase "A Ana tem 30 anos" deu trabalho: "A Ana tem " + str(idade) + " anos", cuidando dos espaços e convertendo o número. A f-string resolve isso de um jeito muito mais limpo: você escreve a frase inteira e põe as variáveis entre chaves, no lugar onde elas devem aparecer: f"A Ana tem {idade} anos". E ela faz mais: mostra um preço com duas casas decimais, alinha as colunas de um cardápio, põe o separador de milhar. É o jeito preferido de montar textos no Python de hoje.

Você vai aprender
  • A pôr variáveis, contas e métodos dentro de um texto com f"…{x}…".
  • A escolher as casas decimais: {preco:.2f}.
  • O separador de milhar ({x:,.2f}) e como chegar ao jeito brasileiro, 1.234,56.
  • A alinhar textos e números em colunas: {nome:<10}, {preco:>8.2f}, {titulo:^20}.
  • Zeros à esquerda (007), porcentagem (25.6%) e chaves de verdade no texto ({{ }}).
  • O {x=}, que mostra o nome e o valor de uma variável, e as f-strings aninhadas do Python 3.12 em diante.
  • Os erros reais: o f esquecido, a chave sem fechar e o Unknown format code 'f'.

A ideia: um formulário com lacunas

Pense num formulário impresso: "Eu, ________, com ____ anos, declaro…". O texto já está pronto; só faltam as lacunas, que cada pessoa preenche com os seus dados. A f-string é esse formulário. As chaves { } são as lacunas, e dentro delas você diz o que vai ali: o Python preenche na hora de criar o texto.

O "f" vem de formatted, "formatado". O nome oficial é "texto formatado literal" (formatted string literal), mas todo mundo diz f-string.


1. A primeira f-string

nome = "Ana"
idade = 30

print(f"Olá, {nome}!")
print(f"A {nome} tem {idade} anos.")
print(f"Daqui a 5 anos, terá {idade + 5}.")
print(f"Em maiúsculas: {nome.upper()}")
f
A letra f colada antes das aspas transforma o texto numa f-string. Sem ela, as chaves são só chaves.
"Olá,
O texto fixo, escrito normalmente.
{nome}
A lacuna: o Python troca {nome} pelo valor da variável nome.
{idade}
Um número. A f-string converte sozinha para texto: nada de str().
{idade + 5}
Dentro das chaves vale qualquer expressão: uma conta, um método, uma função. O Python calcula e põe o resultado.
$ python3 ola.py
Olá, Ana!
A Ana tem 30 anos.
Daqui a 5 anos, terá 35.
Em maiúsculas: ANA

Repare como os espaços ficam naturais: você escreve a frase como ela é, e não precisa lembrar de " " entre os pedaços. E o número 30 entrou no texto sem str() e sem TypeError.

Missão: reescreva o print com uma f-string, sem + e sem str(). A saída deve continuar A Ana tem 30 anos.

idade = 30
print("A Ana tem " + str(idade) + " anos.")
idade = 30
print(f"A Ana tem {idade} anos.")

2. Casas decimais: {preco:.2f}

Depois do nome, dentro das chaves, você pode pôr dois-pontos e um "pedido de formato". O mais usado de todos é o das casas decimais:

preco = 12.5
media = 7.66666

print(f"{preco}")
print(f"{preco:.2f}")
print(f"{media:.2f}")
print(f"{media:.1f}")
print(f"{media:.0f}")
print(f"R$ {preco * 3:.2f}")
$ python3 casas.py
12.5
12.50
7.67
7.7
8
R$ 37.50
preco
O valor.
:
"Agora vem o formato."
.2
Duas casas depois do ponto.
f
De fixed point, "ponto fixo": mostre como número com casas decimais. (Este f não tem nada a ver com o f antes das aspas.)
  • 12.5 com .2f virou 12.50: completou com zero. É o jeito certo de mostrar dinheiro.
  • 7.66666 com .2f virou 7.67: arredondou, não cortou. Com .1f, 7.7; com .0f, 8.
  • A expressão e o formato andam juntos: {preco * 3:.2f} calcula e formata.
  • A variável não muda: preco continua valendo 12.5. O formato vale só para o texto que está sendo montado.
Um detalhe do arredondamento

Quando o número fica exatamente no meio, o Python arredonda para o lado par: f"{2.5:.0f}" dá 2, e f"{3.5:.0f}" dá 4. É a regra do "arredondamento bancário", que evita que os arredondamentos puxem sempre para cima. Para dinheiro com duas casas, isso quase nunca aparece.

Missão: o preço do café saiu como R$ 4.5. Faça sair com duas casas decimais: R$ 4.50.

preco = 4.5
print(f"Café: R$ {preco}")
preco = 4.5
print(f"Café: R$ {preco:.2f}")

3. Separador de milhar, e o jeito brasileiro

Números grandes ficam difíceis de ler: 1234567.891. Uma vírgula (ou um sublinhado) no formato separa os milhares:

salario = 1234567.891

print(f"{salario:,.2f}")
print(f"{salario:_.2f}")
print(f"{1500000:,}")
$ python3 milhar.py
1,234,567.89
1_234_567.89
1,500,000

Mas repare: saiu no jeito americano, com vírgula nos milhares e ponto nos decimais. No Brasil é o contrário: 1.234.567,89. O formato da f-string não tem uma opção "brasileira", então o truque mais usado é trocar os sinais depois, com o replace() da aula Métodos de Texto:

salario = 1234567.891

americano = f"{salario:,.2f}"
brasileiro = americano.replace(",", "X").replace(".", ",").replace("X", ".")

print(americano)
print(brasileiro)
print(f"R$ {brasileiro}")
$ python3 brasileiro.py
1,234,567.89
1.234.567,89
R$ 1.234.567,89
  1. .replace(",", "X"): as vírgulas viram um X provisório: 1X234X567.89.
  2. .replace(".", ","): o ponto decimal vira vírgula: 1X234X567,89.
  3. .replace("X", "."): os X viram pontos: 1.234.567,89.

Por que o X? Se você trocasse direto as vírgulas por pontos, depois não saberia mais quais pontos eram os decimais. O X guarda o lugar, como quando você troca o conteúdo de dois copos usando um terceiro.

E o módulo locale?

O Python tem um módulo, o locale, que formata números do jeito de cada país. Ele depende de como o sistema está configurado (o "pt_BR" precisa estar instalado na máquina), e por isso pode funcionar num computador e falhar em outro. O truque do replace() funciona em qualquer lugar.


4. Alinhando: <, > e ^

Um número logo depois dos dois-pontos diz a largura: quantos caracteres o pedaço deve ocupar, completando com espaços. Um sinal antes dele diz para que lado encostar. Os colchetes no exemplo mostram onde o pedaço começa e termina:

print(f"[{'pão':<10}]")
print(f"[{'pão':>10}]")
print(f"[{'pão':^10}]")
print(f"[{'pão':*^10}]")
print(f"[{'pão':.<10}]")
$ python3 alinhar.py
[pão       ]
[       pão]
[   pão    ]
[***pão****]
[pão.......]
FormatoO que fazComo lembrar
:<10Ocupa 10, encostado à esquerdaA ponta da seta aponta para onde o texto vai
:>10Ocupa 10, encostado à direitaBom para números e preços
:^10Ocupa 10, centralizadoO ^ é um "telhadinho" no meio
:*^10Centralizado, completando com *O caractere antes do sinal é o "enchimento"

Repare nas aspas: dentro de uma f-string com aspas duplas, o texto 'pão' foi escrito com aspas simples. (Desde o Python 3.12, aspas duplas também funcionariam; veja a seção 7.)

Com largura e casas decimais juntas, a Ana monta o cardápio da padaria em colunas. Texto à esquerda, preço à direita:

print(f"{'Produto':<15}{'Preço':>8}")
print(f"{'Pão francês':<15}{0.8:>8.2f}")
print(f"{'Bolo de fubá':<15}{25:>8.2f}")
print(f"{'Café':<15}{4.5:>8.2f}")
$ python3 cardapio.py
Produto           Preço
Pão francês        0.80
Bolo de fubá      25.00
Café               4.50

{0.8:>8.2f} se lê: "8 de largura, encostado à direita, com 2 casas decimais". Assim os pontos decimais ficam todos um embaixo do outro. Os números já se alinham à direita sozinhos, então {0.8:8.2f} daria o mesmo; o > deixa a intenção clara.

Experimente: acrescente uma linha para o "Sonho", de 6 reais, e mude as larguras (15 e 8) para ver o que acontece com as colunas.

print(f"{'Produto':<15}{'Preço':>8}")
print(f"{'Pão francês':<15}{0.8:>8.2f}")
print(f"{'Bolo de fubá':<15}{25:>8.2f}")

5. Zeros, porcentagem e chaves de verdade

pedido = 7
acerto = 0.256

print(f"Pedido nº {pedido:03}")
print(f"Pedido nº {pedido:03d}")
print(f"Acertos: {acerto:.1%}")
print(f"Chaves: {{nome}}")
$ python3 zeros.py
Pedido nº 007
Pedido nº 007
Acertos: 25.6%
Chaves: {nome}
  • :03: largura 3, completando com zeros à esquerda. :03d é o mesmo, dizendo que é um inteiro (d de "decimal", base 10).
  • :.1%: multiplica por 100, põe o % e uma casa decimal. 0.256 virou 25.6%.
  • {{ e }}: para escrever uma chave de verdade numa f-string, dobre-a.

6. {x=}: o nome e o valor, para conferir

Quando um programa não faz o que você espera, é comum espalhar print para ver quanto vale cada variável. Com um = no fim, dentro das chaves, a f-string mostra o nome e o valor de uma vez:

preco = 12.5
quantidade = 3

print(f"{preco=}")
print(f"{quantidade = }")
print(f"{preco * quantidade = }")
print(f"{preco=:.2f}")
$ python3 igual.py
preco=12.5
quantidade = 3
preco * quantidade = 37.5
preco=12.50

Os espaços que você põe em volta do = aparecem na saída. Funciona com contas também (a conta aparece escrita, seguida do resultado), e dá para juntar com um formato: {preco=:.2f}. Use enquanto procura um problema, e apague depois; para conferir programas maiores, existe a aula Depurando com pdb.


7. f-strings dentro de f-strings (Python 3.12 em diante)

Desde o Python 3.12, o que está dentro das chaves pode usar as mesmas aspas da f-string de fora, e até outra f-string:

compras = ["pão", "leite", "café"]
print(f"Comprar: {", ".join(compras)}")

nome = "Ana"
print(f"{f"[{nome}]":>12}")

largura = 10
print(f"{'pão':>{largura}}")
$ python3 aninhada.py
Comprar: pão, leite, café
       [Ana]
       pão
{", ".join(compras)}
Aspas duplas dentro de uma f-string de aspas duplas. O Python entende que as aspas de dentro pertencem à expressão entre chaves.
{f"[{nome}]":>12}
Uma f-string dentro da outra: a de dentro monta [Ana]; a de fora alinha esse texto à direita, em 12 caracteres.
{'pão':>{largura}}
Chaves dentro do formato: a largura vem de uma variável. (Isso funciona em versões bem mais antigas também.)
Se o seu Python for mais antigo

Essa liberdade com as aspas veio no Python 3.12 (a mudança se chama PEP 701). No 3.11 e anteriores, f"{", ".join(compras)}" dá SyntaxError, e você precisa usar o outro tipo de aspas por dentro: f"{', '.join(compras)}". O guia ensina o 3.14, e o Debian 13 traz o 3.13, ambos depois da mudança. Mas, se o seu código vai rodar em computadores antigos, alternar as aspas é o jeito que funciona em todos. (Não deu para rodar um Python 3.11 no laboratório; o comportamento antigo está descrito conforme a documentação oficial.)

Novidade do 3.14: as t-strings 3.14

Com t no lugar do f, como em t"Olá, {nome}!", o Python 3.14 cria uma t-string (de template, "modelo"). Ela não vira texto na hora: vira um objeto do tipo string.templatelib.Template, que guarda as partes fixas e os valores separados, para outro código decidir como juntar (por exemplo, protegendo um site contra textos maliciosos). É um recurso para bibliotecas, não para o dia a dia de quem está começando. Mais em Novidades do Python 3.14 e 3.15.

nome = "Ana"
modelo = t"Olá, {nome}!"
print(type(modelo))
$ python3 tstring.py
<class 'string.templatelib.Template'>

Formas diferentes de montar o mesmo texto

Você vai encontrar, em código mais antigo, outros dois jeitos de formatar: o método format() e o operador %. Todos dão Café: R$ 4.50 (com preco = 4.5):

FormaExemploQuando usar
f-stringf"Café: R$ {preco:.2f}"Sempre, em código novo: é a mais clara (desde o Python 3.6)
format()"Café: R$ {:.2f}".format(preco)Quando o modelo do texto é guardado antes, numa variável, e preenchido depois
%"Café: R$ %.2f" % precoSó para ler código antigo
+ e str()"Café: R$ " + str(preco)Para emendar poucos textos, sem formato (e aqui não daria o .50)

Os formatos depois dos dois-pontos (.2f, >8, ,) são os mesmos na f-string e no format(). A tabela completa está na Referência de Formatação.


Quando dá errado

Esqueceu o f
nome = "Ana"
print("Olá, {nome}!")
$ python3 sem-f.py
Olá, {nome}!

Nenhum erro, e a lacuna não foi preenchida: saiu {nome}, com chaves e tudo. Sem o f, é um texto comum, e as chaves são só caracteres. Como consertar: print(f"Olá, {nome}!"), com o f colado nas aspas.

Chave sem fechar
nome = "Ana"
print(f"Olá, {nome")
$ python3 chave-aberta.py
  File "/home/ana/chave-aberta.py", line 2
    print(f"Olá, {nome")
                      ^
SyntaxError: f-string: expecting '}'

f-string: expecting '}': "na f-string, esperava um }". O ^ aponta a aspa que fechou o texto antes da chave. Não há Traceback: o Python achou o erro só de ler o código. Como consertar: feche a chave, f"Olá, {nome}".

Nome errado dentro das chaves
nome = "Ana"
print(f"Olá, {nomee}!")
$ python3 nome-errado.py
Traceback (most recent call last):
  File "/home/ana/nome-errado.py", line 2, in <module>
    print(f"Olá, {nomee}!")
                  ^^^^^
NameError: name 'nomee' is not defined. Did you mean: 'nome'?

O que está nas chaves é código Python de verdade, e tem as mesmas regras: um nome que não existe dá NameError, com os ^ embaixo dele e a dica Did you mean: 'nome'?. Como consertar: corrija o nome.

Formato de número num texto: Unknown format code 'f'

A Ana lê o preço do teclado e quer mostrar com duas casas:

preco = input("Preço: ")
print(f"R$ {preco:.2f}")
$ python3 formato-texto.py
Preço: 12.5
Traceback (most recent call last):
  File "/home/ana/formato-texto.py", line 2, in <module>
    print(f"R$ {preco:.2f}")
               ^^^^^^^^^^^
ValueError: Unknown format code 'f' for object of type 'str'
ValueError:
"Erro de valor".
Unknown format code 'f'
"Código de formato desconhecido: f".
for object of type 'str'
"…para um objeto do tipo str". O .2f é um formato de número, e o input() sempre devolve texto: "12.5", com aspas.

Como consertar: converta antes, com float() (aula Conversão de Tipos):

preco = float(input("Preço: "))
print(f"R$ {preco:.2f}")
$ python3 formato-texto2.py
Preço: 12.5
R$ 12.50
Formato na ordem errada

A Ana quis o separador de milhar e pôs a vírgula no fim:

total = 1234.5
print(f"{total:.2f,}")
$ python3 virgula-errada.py
Traceback (most recent call last):
  File "/home/ana/virgula-errada.py", line 2, in <module>
    print(f"{total:.2f,}")
            ^^^^^^^^^^^^
ValueError: Invalid format specifier '.2f,' for object of type 'float'

Invalid format specifier '.2f,': "pedido de formato inválido". As partes do formato têm uma ordem fixa: alinhamento e largura, depois o separador, depois as casas e o tipo. Como consertar: {total:,.2f}, com a vírgula antes do ponto.


Referência rápida

Com x = 3.14159, n = 42 e t = "oi":

EscritaO que fazResultado
f"{x}"Põe o valor3.14159
f"{x:.2f}"2 casas decimais3.14
f"{1234567:,}"Separador de milhar1,234,567
f"[{n:>6}]"Largura 6, à direita[    42]
f"[{t:<6}]"Largura 6, à esquerda[oi    ]
f"[{t:^6}]"Largura 6, centralizado[  oi  ]
f"{t:*^6}"Centralizado, com ***oi**
f"{n:05}"Zeros à esquerda00042
f"{0.5:.0%}"Porcentagem50%
f"{n=}"Nome e valorn=42
f"{{ }}"Chaves de verdade{ }
SintomaCausa provável
Saiu {nome} no textoFaltou o f antes das aspas
SyntaxError: f-string: expecting '}'Chave sem fechar
ValueError: Unknown format code 'f' for object of type 'str'Formato de número num texto: converta com float()
ValueError: Invalid format specifierPartes do formato na ordem errada (é :,.2f)
1,234.50 no lugar de 1.234,50O formato é o americano: troque os sinais com replace()

Exercícios

1. A letra mágica

Complete para que {nome} seja trocado pelo valor da variável:

print("Olá, {nome}!")

2. Duas casas

Complete o formato para mostrar 3.14 a partir de x = 3.14159:

print(f"{x:}")

3. O resultado

O que print(f"{2 + 3 = }") mostra?

4. Com preco = 7, o que print(f"R$ {preco:.2f}") mostra?

5. Qual formato encosta o texto à direita, em 10 caracteres?

6. preco = input("Preço: ") e depois f"{preco:.2f}" deu ValueError: Unknown format code 'f' for object of type 'str'. Por quê?

Missão final: o total em reais

Missão: a Ana vende 3 cestas de café da manhã. O preço de cada uma é digitado (aqui, o editor digita 1234.5 por você). O total sai como R$ 3703.5. Faça sair no jeito brasileiro, com separador de milhar e duas casas: Total: R$ 3.703,50.

preco = float(input("Preço da cesta: "))
quantidade = 3
total = preco * quantidade
print(f"Total: R$ {total}")
preco = float(input("Preço da cesta: "))
quantidade = 3
total = preco * quantidade
texto = f"{total:,.2f}".replace(",", "X").replace(".", ",").replace("X", ".")
print(f"Total: R$ {texto}")

Resumo

  • Uma f-string tem um f antes das aspas e lacunas entre chaves: f"Olá, {nome}!". Dentro das chaves vale qualquer expressão, e números entram sem str().
  • Depois de dois-pontos vem o formato: {x:.2f} (casas decimais), {x:,} (milhar), {t:<10} / {t:>10} / {t:^10} (alinhamento), {n:03} (zeros), {p:.1%} (porcentagem).
  • O formato de milhar é o americano; para o brasileiro, troque os sinais com replace() (passando por um caractere provisório).
  • {x=} mostra o nome e o valor: ótimo para conferir.
  • Desde o 3.12, as aspas de dentro podem ser iguais às de fora, e f-strings podem ficar uma dentro da outra.
  • Sem o f, as chaves aparecem no texto; formato de número em texto dá ValueError: Unknown format code 'f'.