Fundamentos
Conversão de tipos em Python: int(), float(), str() e os erros mais comuns
Aprenda a usar int(), float() e str() em Python, a converter o texto do input() em número e a entender o ValueError e o TypeError quando a conversão falha.
Por Prof. Rodrigo Faustino · Atualizado em · 16 min de leitura
Métricas deste artigo
- Palavras
- 3.139
- Caracteres
- 17.474
- Tempo de leitura
- ~16 min
Converter um tipo em outro, em Python, é pedir a uma função que construa um valor novo a partir de um valor que você já tem. A int() devolve um inteiro, a float() devolve um decimal, a str() devolve um texto e a bool() devolve verdadeiro ou falso. A conversão mais importante do começo é a do input(): ele sempre entrega texto, então, para fazer conta com o que a pessoa digitou, é preciso passar pelo int() ou pelo float(). E essa conversão falha com ValueError quando o texto não tem a forma de um número.
Parece um detalhe, mas é a origem de boa parte dos erros de quem está começando e de alguns de quem já programa há tempo. Este artigo mostra o que cada conversão aceita e o que recusa, a diferença entre cortar e arredondar, como tratar o número que o usuário digita com vírgula, o que muda na ESP32 e quais são os problemas que mais se repetem em sala de aula.
O problema: o texto que parece número
No artigo sobre entrada e saída apareceu a regra de que o input() devolve sempre um str. Quem lê isso uma vez costuma esquecer, e o esquecimento aparece assim:
a = input("A: ")
b = input("B: ")
print(a + b)
print(int(a) + int(b))
print(a * 3)Digitando 7 e 8, a saída no Serial é esta:
A: 7
B: 8
78
15
777A primeira conta não somou: juntou dois textos, "7" e "8", e formou "78". A terceira não multiplicou: repetiu o texto três vezes. Só a segunda linha fez a conta que se imaginava, porque cada valor passou pelo int() antes do +. O Python não tem como adivinhar que "7" era para ser número. O texto "7" e o número 7 são coisas diferentes na memória, e o + olha o tipo para decidir o que fazer.
Por isso o input() não devolve número direto: quem digita pode estar informando um nome, uma senha, uma data ou uma idade, e só o programador sabe qual das hipóteses vale. O texto é o denominador comum, e a conversão fica por conta de quem escreve o programa.
Da ementa ao semestre planejado
- Plano de ensino e calendário montados sozinhos
- Diário de aulas pronto para colar no SIGA
- Slides e listas de exercícios com gabarito
Versão Community grátis · Windows
As quatro conversões
| Função | O que devolve | Exemplo | Resultado |
|---|---|---|---|
int() | número inteiro | int("42") | 42 |
float() | número decimal | float("3.5") | 3.5 |
str() | texto | str(42) | "42" |
bool() | verdadeiro ou falso | bool("x") | True |
print(int("42"), int(3.9), float("3.5"), float(7), str(42), bool("x"))
print(int(" 42 "), int("-5"), int("+5"), int("007"))
print(float(" 2.5 "), float("1e3"), float("3"))
print(str(3.0), str(True), str(None))
print(type(int("42")), type(str(42)))
print(int("ff", 16), int("101", 2))A saída mostra 42 3 3.5 7.0 42 True na primeira linha. Repare que int(3.9) vale 3 e não 4: a conversão de decimal para inteiro corta a parte decimal, sem arredondar. A segunda linha mostra que o int() tolera espaços nas pontas, aceita sinal e ignora zeros à esquerda: o resultado é 42 -5 5 7. A terceira mostra o mesmo para o float(), que ainda entende notação científica: float("1e3") vale 1000.0. A última linha usa o segundo argumento do int(), a base. int("ff", 16) lê o texto como hexadecimal e dá 255, e int("101", 2) lê como binário e dá 5. Para quem mexe com registradores e máscaras de bits na ESP32, isso aparece cedo.
O que o int() e o float() aceitam e o que recusam
As duas funções leem o texto com regras fixas. Aceitam dígitos, um sinal opcional no começo e espaços nas pontas. O float() aceita também o ponto decimal e o expoente. Tudo o que fugir disso é recusado com ValueError.
Quatro casos merecem ser decorados, porque são os que mais derrubam programas. O primeiro é int("3.5"): o texto tem ponto, e o int() só aceita dígitos, então dá erro, embora int(3.5) com o número direto funcione e devolva 3. O segundo é o texto vazio, int("") ou float(""), que é o que chega quando alguém aperta Enter sem digitar nada. O terceiro é o texto com lixo no final, como int("12abc"). O quarto é o espaço no meio, int("4 2"): as pontas são toleradas, o meio não.
E existe um quinto, que não é ValueError, e sim TypeError: int(None). O None não é texto nem número, e o Python não sabe o que fazer com ele. Isso costuma acontecer quando uma função devolve None por esquecer o return e o resultado é passado direto ao int().
O str() e a junção com texto
O str() faz o caminho contrário: transforma qualquer valor em texto, o que é necessário quando se quer juntar um número a uma frase com o +. Sem a conversão, o Python recusa a conta.
n = 7
print("Voce tem " + str(n) + " anos")
print("Voce tem", n, "anos")
print(f"Voce tem {n} anos")
print("5" * 2, int("5") * 2)
print(str(3) + str(4), 3 + 4)
print(len(str(12345)), len(str(-12)))
print(str(12345)[0], int(str(12345)[0]) + 1)As três primeiras linhas mostram a mesma frase, Voce tem 7 anos, de três jeitos. A vírgula do print() e a f-string convertem sozinhas, e só o + exige o str(). A quarta linha repete a lição do começo: "5" * 2 vale 55 e int("5") * 2 vale 10. A quinta mostra 34 contra 7. As duas últimas usam uma ideia que aparece em exercícios: transformar um número em texto para olhar os dígitos. len(str(12345)) vale 5, a quantidade de dígitos, e str(12345)[0] é o texto "1", o primeiro dígito, que volta a virar número com o int() e soma 1 para dar 2.
O bool() e a surpresa do texto "False"
O bool() devolve False para o que é vazio ou zero (0, 0.0, "", [], None) e True para o resto. A consequência incômoda é que o texto "0", o texto "False" e até um espaço são todos verdadeiros, porque nenhum deles é vazio. Se você ler uma resposta com input() e passar por bool(), o usuário que digitar False vai receber True. A decisão sobre o que fazer com respostas de texto fica para o próximo módulo da série, que trata de if e comparações.
Conversão implícita e explícita
Em algumas contas o Python converte sozinho, e em outras se recusa. Vale saber a diferença, porque o erro vem sempre do mesmo lugar: esperar uma conversão automática que não existe.
print(3 + 4.0, type(3 + 4.0))
print(True + 1, type(True + 1))
print(5 == 5.0, "5" == 5, 1 < 2.5)
print(int("5") + 5, "5" + str(5))A saída tem 7.0 <class 'float'> na primeira linha. Ao misturar um inteiro com um decimal, o Python promove o inteiro para float e devolve decimal. Na segunda linha, True + 1 vale 2, porque o booleano se comporta como o inteiro 1 numa conta. A terceira mostra que 5 == 5.0 é verdadeiro, mas "5" == 5 é falso: o texto e o número nunca são iguais, mesmo que se escrevam igual. A última linha mostra os dois jeitos de resolver uma mistura: converter o texto para número e somar (10), ou converter o número para texto e juntar (55).
A regra que resume tudo: o Python converte sozinho de inteiro para decimal e de booleano para inteiro dentro de uma conta. Entre texto e número, nunca. Essa conversão precisa estar escrita no código, e é por isso que se chama conversão explícita.
O int() corta, o round() arredonda, o // desce
A conversão de decimal para inteiro tem três caminhos, e eles dão respostas diferentes.
print(int(3.7), round(3.7), 3.7 // 1)
print(int(-3.7), round(-3.7), -3.7 // 1)
print(round(3.5), round(4.5), round(-2.5))
print(type(round(3.7)), type(round(3.7, 1)), type(3.7 // 1))A primeira linha dá 3 4 3.0: o int() cortou, o round() foi para o inteiro mais próximo e o // desceu, mantendo o tipo float. A segunda linha, com o número negativo, mostra a diferença que passa batida com positivos: -3 -4 -4.0. O int() vai em direção ao zero, e o // continua descendo. A terceira linha repete a surpresa já vista no artigo sobre operadores aritméticos: round(4.5) vale 4 e round(-2.5) vale -2, porque, no meio exato entre dois inteiros, o Python escolhe o par. A última linha mostra que round(x) com um argumento devolve int, mas round(x, 1) com duas casas devolve float, e que o // com decimais devolve float.
Na prática, a pergunta que escolhe a ferramenta é: "o que eu quero fazer com a parte decimal?". Para descartá-la, int(). Para chegar ao inteiro mais próximo, round(). Para o maior inteiro que não passa do número, o // ou o math.floor().
A IA que lembra da sua vida e mora no seu computador
- Memória de longo prazo com a fonte de cada resposta
- Funciona offline: seus dados ficam no seu PC
- Lê PDFs, slides, fotos e gravações de reunião
Plano Essencial grátis para sempre
Convertendo o que vem do input()
O padrão de uso mais comum junta as duas funções numa linha só:
idade = input("Idade: ")
print(type(idade))
idade = int(idade)
print(type(idade), idade + 1)Digitando 17, a saída é:
Idade: 17
<class 'str'>
<class 'int'> 18Na prática, a conversão e a leitura costumam ficar juntas: idade = int(input("Idade: ")). A leitura dessa linha vai de dentro para fora. Primeiro o input() mostra a pergunta e devolve o texto. Depois o int() recebe esse texto e devolve o número. Só no fim o nome idade passa a apontar para o inteiro. O texto original some, porque nenhum nome ficou apontando para ele.
A vírgula decimal do brasileiro
Quem digita uma nota no Brasil escreve 7,5. O float("7,5") dá ValueError, porque o Python só conhece o ponto como separador decimal. A saída é trocar a vírgula por ponto antes de converter, com o método .replace():
n1 = float(input("Nota 1: ").replace(",", "."))
n2 = float(input("Nota 2: ").replace(",", "."))
print("Media:", (n1 + n2) / 2)Com 7,5 e 8 de entrada:
Nota 1: 7,5
Nota 2: 8
Media: 7.75
A cadeia input(...).replace(",", ".") lê o texto e já troca a vírgula; o float() por fora converte. A troca é inofensiva para quem digitou com ponto, porque se não há vírgula o texto passa inalterado. O caminho inverso, para mostrar o resultado com vírgula, também existe: str(7.5).replace(".", ",") dá 7,5.
O mesmo vale para o valor que vem com símbolo. O texto "R$ 12,50" precisa perder o "R$ " e ganhar o ponto antes do float(), e isso se escreve com dois .replace() em sequência, que dão 12.5.
Quando o texto não é número
Se a pessoa digita tres quando o programa pede um número, a conversão levanta o erro e o programa para:
n = int(input("Quantos? "))Quantos? tres
Traceback (most recent call last):
File "main.py", line 1, in <module>
ValueError: invalid syntax for integer with base 10A mensagem aponta a linha, mas não mostra o texto que falhou. Esse é um dos pontos em que o MicroPython é mais econômico que o Python do computador, como a tabela mais abaixo detalha. Para os programas que precisam sobreviver ao que o usuário digita, existem duas defesas, e a série volta a elas com calma mais adiante.
A primeira é perguntar ao texto se ele é feito só de dígitos, com o método .isdigit(), e tirar os espaços das pontas com .strip():
print("42".isdigit(), "-5".isdigit(), "3.5".isdigit(), "".isdigit(), "abc".isdigit())
print(" 7 ".isdigit(), " 7 ".strip().isdigit())A saída é True False False False False na primeira linha e False True na segunda. O .isdigit() só aceita dígitos, então recusa os negativos e os decimais, e o .strip() resolve o espaço que sobrou do teclado. É um filtro para inteiros positivos, e só.
A segunda defesa é tentar converter e reagir ao fracasso. O bloco try roda o código que pode falhar, e o except ValueError diz o que fazer se a falha for aquele erro:
texto = "3.5"
try:
n = int(texto)
except ValueError:
n = 0
print(n)Aqui a saída é 0. Trocando texto por "42", a saída passa a ser 42. O assunto ganha um artigo próprio mais adiante na série, junto com os outros tipos de erro. Por ora, basta saber que o try existe e que ele captura exatamente o ValueError do int() e do float().
O que muda na ESP32
O comportamento das conversões é o mesmo no MicroPython e no Python do computador. Mudam as mensagens de erro e, por causa do float de 32 bits, alguns resultados de contas com decimais.
| Situação | MicroPython | Python no computador |
|---|---|---|
int("3.5") | ValueError: invalid syntax for integer with base 10 | ValueError: invalid literal for int() with base 10: '3.5' |
float("abc") | ValueError: invalid syntax for number | ValueError: could not convert string to float: 'abc' |
int(None) | TypeError: can't convert NoneType to int | TypeError: int() argument must be a string, a bytes-like object or a real number, not 'NoneType' |
5 + "5" | TypeError: unsupported types for __add__: 'int', 'str' | TypeError: unsupported operand type(s) for +: 'int' and 'str' |
"a" < 1 | TypeError: unsupported types for __lt__: 'str', 'int' | TypeError: '<' not supported between instances of 'str' and 'int' |
A diferença que mais atrapalha na hora de depurar é a primeira: o Python do computador mostra o texto que falhou ('3.5'), e o MicroPython não mostra. Quando o ValueError aparecer numa placa, imprima o texto antes de converter, com print(repr(texto)). O repr() mostra as aspas e deixa visíveis os espaços e o texto vazio, que a leitura normal esconde.
A conta dos centavos
A segunda diferença é mais sutil e afeta quem trabalha com dinheiro. Converter com int() uma conta que deu um fio abaixo do valor exato tira um centavo, e a conta "um fio abaixo" depende de quantos bits o float tem.
print(19.99 * 100)
print(int(19.99 * 100))
print(round(19.99 * 100))
print(int(0.29 * 100), round(0.29 * 100))
print(int((0.1 + 0.7) * 10), round((0.1 + 0.7) * 10))No simulador, a saída é 1999.0, 1999, 1999, 29 29 e 8 8. No Python do computador, as mesmas linhas mostram 1998.9999999999998, 1998, 1999, 28 29 e 7 8. O float de 64 bits do computador não consegue guardar 19,99 exatamente, e a multiplicação por 100 deixa um resto minúsculo abaixo de 1999. O int() corta esse resto e perde um centavo. Na ESP32, o float tem menos bits, o arredondamento interno cai do outro lado e a conta fecha em 1999.
Não é um caso em que a ESP32 acerta e o computador erra. O número 19,99 não existe exatamente em nenhuma das duas máquinas, e o programa que depende de a conta cair do lado certo está errado nas duas, só que o defeito aparece em lugares diferentes. Duas saídas resolvem de verdade. A primeira é trocar o int() por round(), que dá 1999 nas duas máquinas. A segunda é nunca guardar dinheiro como decimal: guardar centavos como inteiro (1999) e só dividir por 100 na hora de mostrar. Inteiros do Python são exatos.
Problemas que aparecem em sala de aula
Os problemas abaixo se repetem de turma em turma e de ano em ano. Quem ensina programação reconhece cada um, e quem está aprendendo costuma passar por vários.
A vírgula que o aluno digita
Alguém pede a nota ao usuário, digita 7,5 para testar o próprio programa e vê o ValueError. A reação é achar que o float() está quebrado, porque, afinal, "7,5 é um número". O erro está na expectativa: o Python só reconhece o ponto. A saída é o .replace(",", ".") visto acima, e vale transformar isso num hábito de toda leitura de decimal.
O Enter pressionado para ver o que acontece
O programa roda bem nos testes, com todos os valores bonitos. Na hora de mostrar ao colega, o colega aperta Enter sem digitar nada, e o int("") derruba o programa com ValueError. É o erro mais fácil de provocar e um dos mais esquecidos na hora de testar. Um bom hábito de teste é, antes de entregar, rodar o programa e apertar Enter em todas as perguntas.
O decimal onde só cabia inteiro
Quem escreve idade = int(input("Idade: ")) e digita 17.5 leva ValueError, e fica surpreso, porque tem a impressão de que o int() "converte qualquer número". Ele converte número em número. Texto com ponto não é um inteiro. Se o programa precisa aceitar os dois, o caminho é ler como decimal e, depois, decidir o que fazer com a parte decimal: int(float(texto)) corta, e round(float(texto)) arredonda.
O resultado da conversão jogado fora
Este é o erro de quem acredita que o int() transforma a variável:
idade = "17"
int(idade)
print(idade + 1)Traceback (most recent call last):
File "main.py", line 3, in <module>
TypeError: unsupported types for __add__: 'str', 'int'A linha 2 chama o int(), que devolve o número 17, e esse número não vai para lugar nenhum. A variável idade continua apontando para o texto. A função devolve um valor novo e não altera o antigo. A correção é guardar o resultado: idade = int(idade). O mesmo vale para str(), float() e para quase todo método de texto.
O 53 no lugar do 8
Sem erro, só com o resultado errado: o programa pede dois números, soma e mostra 53 em vez de 8. O erro está na falta de conversão, e como o programa roda sem reclamar, é o que mais demora a ser encontrado por quem está começando. O diagnóstico mais rápido é imprimir o tipo, print(type(a)), ou o valor com aspas, print(repr(a)). Se aparecer '5' entre aspas, é texto.
Converter um dos dois
Alguém lembra de converter o primeiro valor e esquece do segundo: int(a) + b. O resultado é o TypeError da tabela acima, unsupported types for __add__: 'int', 'str'. A mensagem é correta, mas não diz qual das duas variáveis é texto, e é comum olhar para a variável errada. Quando o TypeError aparecer numa soma, confira o tipo dos dois lados.
O int() usado como round()
Quem converte uma nota 6.9 com int(6.9) e recebe 6 costuma achar que o Python errou. A conversão cortou, como sempre faz. Em cálculos de média, de desconto e de porcentagem, a escolha entre cortar e arredondar muda o resultado final e precisa ser uma decisão, não um acaso. Ao escrever int(...) numa conta, vale perguntar a si mesmo se o "pra baixo" é mesmo o que o problema pede.
Exercício: a conta do restaurante
Um restaurante cobra 10% de serviço. Escreva um programa que leia o valor da conta como o usuário digita, com vírgula, e mostre o total com o serviço, com duas casas e com vírgula. Pense primeiro nos passos: ler o texto, trocar a vírgula, converter, multiplicar por 1,10, arredondar e trocar o ponto de volta para vírgula.
texto = input("Valor da conta: ")
valor = float(texto.replace(",", "."))
total = valor * 1.10
print("Total com 10%:", round(total, 2))
print("Total com 10%:", str(round(total, 2)).replace(".", ","))
centavos = round(valor * 100)
print(centavos, centavos * 110 // 100)Com 47,90 de entrada, a saída é:
Valor da conta: 47,90
Total com 10%: 52.69
Total com 10%: 52,69
4790 5269A primeira linha mostra o resultado com ponto, que serve para o Python. A segunda converte o número em texto, troca o ponto e mostra 52,69, como o usuário espera ler. As duas últimas linhas fazem a mesma conta em centavos inteiros: round(valor * 100) dá 4790, e 4790 * 110 // 100 dá 5269. Repare que o round() aparece de novo na conversão para centavos, pelo motivo da seção anterior. Teste com 47 (sem vírgula nenhuma), com abc e com o campo vazio, para ver o que acontece em cada caso e conferir se o programa faz o que o usuário espera.
Perguntas frequentes
Por que o int("3.5") dá erro e o int(3.5) não?
Porque são duas entradas de natureza diferente. Com o número, o int() corta a parte decimal. Com o texto, ele tenta ler um inteiro escrito em dígitos, e o ponto não é dígito. Para converter "3.5" em inteiro, passe primeiro pelo float(): int(float("3.5")) dá 3.
Preciso converter para mostrar um número com o print()?
Não. O print() aceita qualquer tipo e converte sozinho para mostrar. A conversão com str() só é obrigatória quando você junta o número a um texto com o sinal de +.
Como mostrar um decimal com duas casas?
Com a f-string: f"{x:.2f}". Para x = 52.69, mostra 52.69. O :.2f não altera o valor, só a forma de mostrá-lo. Se você precisa do valor arredondado para continuar calculando, use round(x, 2).
O float() aceita a vírgula, se eu trocar a configuração do computador?
Não. O Python não consulta a configuração regional para ler número. O ponto é sempre o separador decimal no código e nas conversões, e o .replace() é o jeito de lidar com a entrada em português.
Para continuar
A trilha Lógica com Python tem desafios que cobram exatamente essas conversões. O Soma de dois e o Dobro de um número são o aquecimento com int(input()), o Média de notas junta conversão e divisão, e o Desconto de 10% cobra o cuidado com decimais. Se algum ponto ficou solto, releia o artigo sobre variáveis e tipos, que explica os quatro tipos que aqui aparecem em movimento, e o texto sobre operadores aritméticos.
O próximo assunto da série abre o módulo de decisão: os operadores relacionais e lógicos, ==, <, and, or e not. Com eles, o programa deixa de repetir sempre a mesma sequência e passa a escolher o caminho conforme o valor que acabou de ser convertido.