Saltar al contenido
IDE libre

Fundamentos

Conversión de tipos en Python: int(), float(), str() y los errores más comunes

Aprende int(), float() y str() en Python, a convertir el texto de input() en número y a entender el ValueError y el TypeError cuando la conversión falla.

Por Prof. Rodrigo Faustino · Actualizado el · 16 min de lectura

Métricas de este artículo

Palabras
3169
Caracteres
18.190
Tiempo de lectura
~16 min

Convertir un tipo en otro, en Python, es pedirle a una función que construya un valor nuevo a partir de un valor que ya tienes. La int() devuelve un entero, la float() devuelve un decimal, la str() devuelve un texto y la bool() devuelve verdadero o falso. La conversión más importante del comienzo es la de input(): siempre entrega texto, así que, para hacer cuentas con lo que la persona escribió, hay que pasar por int() o por float(). Y esa conversión falla con ValueError cuando el texto no tiene la forma de un número.

Parece un detalle, pero es el origen de buena parte de los errores de quien está empezando y de algunos de quien ya programa hace tiempo. Este artículo muestra qué acepta y qué rechaza cada conversión, la diferencia entre cortar y redondear, cómo tratar el número que el usuario escribe con coma, qué cambia en la ESP32 y cuáles son los problemas que más se repiten en el aula.

El problema: el texto que parece número

En el artículo sobre entrada y salida apareció la regla de que input() devuelve siempre un str. Quien lo lee una vez suele olvidarlo, y el olvido aparece así:

a = input("A: ")
b = input("B: ")
print(a + b)
print(int(a) + int(b))
print(a * 3)

Escribiendo 7 y 8, la salida en el Serial es esta:

A: 7
B: 8
78
15
777

La primera cuenta no sumó: juntó dos textos, "7" y "8", y formó "78". La tercera no multiplicó: repitió el texto tres veces. Solo la segunda línea hizo la cuenta que se imaginaba, porque cada valor pasó por int() antes del +. Python no tiene cómo adivinar que "7" era para ser número. El texto "7" y el número 7 son cosas distintas en la memoria, y el + mira el tipo para decidir qué hacer.

Por eso input() no devuelve número directo: quien escribe puede estar informando un nombre, una contraseña, una fecha o una edad, y solo el programador sabe cuál de las hipótesis vale. El texto es el denominador común, y la conversión queda por cuenta de quien escribe el programa.

FastMindAsistente de IA local

La IA que recuerda tu vida y vive en tu ordenador

  • Memoria a largo plazo con la fuente de cada respuesta
  • Funciona sin conexión: tus datos se quedan en tu PC
  • Lee PDF, diapositivas, fotos y grabaciones de reuniones
Descargar gratis para Windows

Plan Esencial gratis para siempre

Las cuatro conversiones

FunciónQué devuelveEjemploResultado
int()número enteroint("42")42
float()número decimalfloat("3.5")3.5
str()textostr(42)"42"
bool()verdadero o falsobool("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))

La salida muestra 42 3 3.5 7.0 42 True en la primera línea. Fíjate en que int(3.9) vale 3 y no 4: la conversión de decimal a entero corta la parte decimal, sin redondear. La segunda línea muestra que int() tolera espacios en los extremos, acepta signo e ignora ceros a la izquierda: el resultado es 42 -5 5 7. La tercera muestra lo mismo para float(), que además entiende notación científica: float("1e3") vale 1000.0. La última línea usa el segundo argumento de int(), la base. int("ff", 16) lee el texto como hexadecimal y da 255, e int("101", 2) lo lee como binario y da 5. Para quien trabaja con registros y máscaras de bits en la ESP32, esto aparece pronto.

Qué aceptan y qué rechazan int() y float()

Las dos funciones leen el texto con reglas fijas. Aceptan dígitos, un signo opcional al comienzo y espacios en los extremos. float() acepta también el punto decimal y el exponente. Todo lo que se salga de eso se rechaza con ValueError.

Tres tarjetas en línea: str con el valor "42", int con 42 y float con 42.0. Flechas rotuladas int("42"), str(42), float(42) e int(3.9) es 3 unen las tarjetas. Abajo, tres cuadros: lo que convierte, como int("42") y float("3.5"); lo que da ValueError, como int("3.5") y float("abc"); y lo que da TypeError, como int(None) y "5" + 5.
Hacia dónde lleva cada conversión, y los casos que Python rechaza con ValueError o TypeError.

Cuatro casos merecen memorizarse, porque son los que más derriban programas. El primero es int("3.5"): el texto tiene punto, y int() solo acepta dígitos, así que da error, aunque int(3.5) con el número directo funcione y devuelva 3. El segundo es el texto vacío, int("") o float(""), que es lo que llega cuando alguien pulsa Enter sin escribir nada. El tercero es el texto con basura al final, como int("12abc"). El cuarto es el espacio en el medio, int("4 2"): los extremos se toleran, el medio no.

Y existe un quinto, que no es ValueError, sino TypeError: int(None). El None no es texto ni número, y Python no sabe qué hacer con él. Esto suele ocurrir cuando una función devuelve None por olvidar el return y el resultado se pasa directo a int().

El str() y la unión con texto

El str() hace el camino contrario: transforma cualquier valor en texto, lo que es necesario cuando se quiere unir un número a una frase con el +. Sin la conversión, Python rechaza la cuenta.

n = 7
print("Tienes " + str(n) + " años")
print("Tienes", n, "años")
print(f"Tienes {n} años")
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)

Las tres primeras líneas muestran la misma frase, Tienes 7 años, de tres maneras. La coma del print() y la f-string convierten solas, y solo el + exige str(). La cuarta línea repite la lección del comienzo: "5" * 2 vale 55 e int("5") * 2 vale 10. La quinta muestra 34 contra 7. Las dos últimas usan una idea que aparece en ejercicios: transformar un número en texto para mirar los dígitos. len(str(12345)) vale 5, la cantidad de dígitos, y str(12345)[0] es el texto "1", el primer dígito, que vuelve a ser número con int() y suma 1 para dar 2.

El bool() y la sorpresa del texto "False"

El bool() devuelve False para lo que es vacío o cero (0, 0.0, "", [], None) y True para el resto. La consecuencia incómoda es que el texto "0", el texto "False" e incluso un espacio son todos verdaderos, porque ninguno está vacío. Si lees una respuesta con input() y la pasas por bool(), el usuario que escriba False va a recibir True. La decisión sobre qué hacer con respuestas de texto queda para el próximo módulo de la serie, que trata de if y comparaciones.

Conversión implícita y explícita

En algunas cuentas Python convierte solo, y en otras se niega. Conviene saber la diferencia, porque el error viene siempre del mismo lugar: esperar una conversión automática que no 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))

La salida tiene 7.0 <class 'float'> en la primera línea. Al mezclar un entero con un decimal, Python promueve el entero a float y devuelve decimal. En la segunda línea, True + 1 vale 2, porque el booleano se comporta como el entero 1 en una cuenta. La tercera muestra que 5 == 5.0 es verdadero, pero "5" == 5 es falso: el texto y el número nunca son iguales, aunque se escriban igual. La última línea muestra las dos formas de resolver una mezcla: convertir el texto a número y sumar (10), o convertir el número a texto y unir (55).

La regla que resume todo: Python convierte solo de entero a decimal y de booleano a entero dentro de una cuenta. Entre texto y número, nunca. Esa conversión tiene que estar escrita en el código, y por eso se llama conversión explícita.

El int() corta, el round() redondea, el // baja

La conversión de decimal a entero tiene tres caminos, y dan respuestas distintas.

Dos rectas numéricas. En la de la izquierda, el punto 3.7 entre 3 y 4: int y la división entera llevan a 3, round lleva a 4. En la de la derecha, el punto menos 3.7 entre menos 4 y menos 3: int va hacia menos 3, rumbo al cero, mientras round y la división entera van hacia menos 4. Abajo, los resultados: int(3.7) es 3, round(3.7) es 4, 3.7 // 1 es 3.0, int(-3.7) es -3, round(-3.7) es -4 y -3.7 // 1 es -4.0.
int() corta la parte decimal en dirección al cero, round() va al entero más cercano y // siempre baja.
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))

La primera línea da 3 4 3.0: el int() cortó, el round() fue al entero más cercano y el // bajó, manteniendo el tipo float. La segunda línea, con el número negativo, muestra la diferencia que pasa desapercibida con positivos: -3 -4 -4.0. El int() va en dirección al cero, y el // sigue bajando. La tercera línea repite la sorpresa ya vista en el artículo sobre operadores aritméticos: round(4.5) vale 4 y round(-2.5) vale -2, porque, en el medio exacto entre dos enteros, Python elige el par. La última línea muestra que round(x) con un argumento devuelve int, pero round(x, 1) con dos devuelve float, y que el // con decimales devuelve float.

En la práctica, la pregunta que elige la herramienta es: "¿qué quiero hacer con la parte decimal?". Para descartarla, int(). Para llegar al entero más cercano, round(). Para el mayor entero que no pasa del número, el // o math.floor().

FastTeacherPara profesores

Del programa al semestre planificado

  • Plan de enseñanza y calendario montados solos
  • Diario de clases listo para pegar en el SIGA
  • Diapositivas y listas de ejercicios con solucionario
Conocer FastTeacher

Versión Community gratis · Windows

Convirtiendo lo que viene de input()

El patrón de uso más común junta las dos funciones en una sola línea:

idade = input("Edad: ")
print(type(idade))
idade = int(idade)
print(type(idade), idade + 1)

Escribiendo 17, la salida es:

Edad: 17
<class 'str'>
<class 'int'> 18

En la práctica, la conversión y la lectura suelen ir juntas: idade = int(input("Edad: ")). La lectura de esa línea va de adentro hacia afuera. Primero input() muestra la pregunta y devuelve el texto. Después int() recibe ese texto y devuelve el número. Solo al final el nombre idade pasa a apuntar al entero. El texto original desaparece, porque ningún nombre quedó apuntando a él.

La coma decimal del hispanohablante

Quien escribe una nota con la costumbre de la coma teclea 7,5. El float("7,5") da ValueError, porque Python solo conoce el punto como separador decimal. La salida es cambiar la coma por punto antes de convertir, con el método .replace():

n1 = float(input("Nota 1: ").replace(",", "."))
n2 = float(input("Nota 2: ").replace(",", "."))
print("Promedio:", (n1 + n2) / 2)

Con 7,5 y 8 de entrada:

Nota 1: 7,5
Nota 2: 8
Promedio: 7.75
El IDE de PyPlaca con el programa de las dos notas en el editor. En el Serial, Nota 1 recibe 7,5 con coma, Nota 2 recibe 8, y el promedio aparece como 7.75.
La nota escrita con coma pasa por el replace() antes del float(), y el promedio sale correcto en el Serial.

La cadena input(...).replace(",", ".") lee el texto y ya cambia la coma; el float() de afuera convierte. El cambio es inofensivo para quien escribió con punto, porque si no hay coma el texto pasa sin alteración. El camino inverso, para mostrar el resultado con coma, también existe: str(7.5).replace(".", ",") da 7,5.

Lo mismo vale para el valor que viene con símbolo. El texto "R$ 12,50" tiene que perder el "R$ " y ganar el punto antes del float(), y eso se escribe con dos .replace() en secuencia, que dan 12.5.

Cuando el texto no es número

Si la persona escribe tres cuando el programa pide un número, la conversión levanta el error y el programa se detiene:

n = int(input("¿Cuántos? "))
¿Cuántos? tres
Traceback (most recent call last):
  File "main.py", line 1, in <module>
ValueError: invalid syntax for integer with base 10

El mensaje señala la línea, pero no muestra el texto que falló. Este es uno de los puntos en que MicroPython es más económico que el Python del computador, como detalla la tabla más abajo. Para los programas que necesitan sobrevivir a lo que el usuario escribe, existen dos defensas, y la serie vuelve a ellas con calma más adelante.

La primera es preguntarle al texto si está hecho solo de dígitos, con el método .isdigit(), y quitar los espacios de los extremos con .strip():

print("42".isdigit(), "-5".isdigit(), "3.5".isdigit(), "".isdigit(), "abc".isdigit())
print(" 7 ".isdigit(), " 7 ".strip().isdigit())

La salida es True False False False False en la primera línea y False True en la segunda. El .isdigit() solo acepta dígitos, así que rechaza los negativos y los decimales, y el .strip() resuelve el espacio que sobró del teclado. Es un filtro para enteros positivos, y nada más.

La segunda defensa es intentar convertir y reaccionar al fracaso. El bloque try ejecuta el código que puede fallar, y el except ValueError dice qué hacer si la falla es ese error:

texto = "3.5"
try:
    n = int(texto)
except ValueError:
    n = 0
print(n)

Aquí la salida es 0. Cambiando texto por "42", la salida pasa a ser 42. El tema gana un artículo propio más adelante en la serie, junto con los otros tipos de error. Por ahora, basta saber que el try existe y que captura exactamente el ValueError de int() y de float().

Qué cambia en la ESP32

El comportamiento de las conversiones es el mismo en MicroPython y en el Python del computador. Cambian los mensajes de error y, por el float de 32 bits, algunos resultados de cuentas con decimales.

SituaciónMicroPythonPython en el computador
int("3.5")ValueError: invalid syntax for integer with base 10ValueError: invalid literal for int() with base 10: '3.5'
float("abc")ValueError: invalid syntax for numberValueError: could not convert string to float: 'abc'
int(None)TypeError: can't convert NoneType to intTypeError: 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" < 1TypeError: unsupported types for __lt__: 'str', 'int'TypeError: '<' not supported between instances of 'str' and 'int'

La diferencia que más estorba a la hora de depurar es la primera: el Python del computador muestra el texto que falló ('3.5'), y MicroPython no lo muestra. Cuando el ValueError aparezca en una placa, imprime el texto antes de convertir, con print(repr(texto)). El repr() muestra las comillas y deja visibles los espacios y el texto vacío, que la lectura normal esconde.

La cuenta de los centavos

La segunda diferencia es más sutil y afecta a quien trabaja con dinero. Convertir con int() una cuenta que dio un pelo por debajo del valor exacto quita un centavo, y la cuenta "un pelo por debajo" depende de cuántos bits tiene el float.

Tabla con tres columnas: expresión, computador de 64 bits y ESP32 con simulador de 32 bits. 19.99 por 100 da 1998.9999999999998 en el computador y 1999.0 en la ESP32. int de 19.99 por 100 da 1998 en el computador, en rojo, y 1999 en la ESP32. int de 0.29 por 100 da 28 contra 29. round de 19.99 por 100 da 1999 en las dos.
El mismo int() da resultados distintos en el computador y en la ESP32 cuando la cuenta de centavos queda un pelo por debajo del valor exacto. El round() da la misma respuesta en los dos.
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))

En el simulador, la salida es 1999.0, 1999, 1999, 29 29 y 8 8. En el Python del computador, las mismas líneas muestran 1998.9999999999998, 1998, 1999, 28 29 y 7 8. El float de 64 bits del computador no consigue guardar 19,99 exactamente, y la multiplicación por 100 deja un resto minúsculo por debajo de 1999. El int() corta ese resto y pierde un centavo. En la ESP32, el float tiene menos bits, el redondeo interno cae del otro lado y la cuenta cierra en 1999.

No es un caso en que la ESP32 acierta y el computador se equivoca. El número 19,99 no existe exactamente en ninguna de las dos máquinas, y el programa que depende de que la cuenta caiga del lado correcto está mal en las dos, solo que el defecto aparece en lugares distintos. Dos salidas resuelven de verdad. La primera es cambiar el int() por round(), que da 1999 en las dos máquinas. La segunda es no guardar nunca dinero como decimal: guardar centavos como entero (1999) y solo dividir entre 100 a la hora de mostrar. Los enteros de Python son exactos.

Problemas que aparecen en el aula

Los problemas de abajo se repiten de grupo en grupo y de año en año. Quien enseña programación reconoce cada uno, y quien está aprendiendo suele pasar por varios.

La coma que escribe el alumno

Alguien pide la nota al usuario, escribe 7,5 para probar su propio programa y ve el ValueError. La reacción es creer que el float() está roto, porque, al fin y al cabo, "7,5 es un número". El error está en la expectativa: Python solo reconoce el punto. La salida es el .replace(",", ".") visto arriba, y vale la pena convertirlo en un hábito de toda lectura de decimal.

El Enter pulsado para ver qué pasa

El programa corre bien en las pruebas, con todos los valores bonitos. A la hora de mostrárselo al compañero, el compañero pulsa Enter sin escribir nada, y el int("") derriba el programa con ValueError. Es el error más fácil de provocar y uno de los más olvidados a la hora de probar. Un buen hábito de prueba es, antes de entregar, ejecutar el programa y pulsar Enter en todas las preguntas.

El decimal donde solo cabía un entero

Quien escribe idade = int(input("Edad: ")) y teclea 17.5 recibe ValueError, y se sorprende, porque tiene la impresión de que int() "convierte cualquier número". Convierte número en número. Un texto con punto no es un entero. Si el programa necesita aceptar los dos, el camino es leer como decimal y, después, decidir qué hacer con la parte decimal: int(float(texto)) corta, y round(float(texto)) redondea.

El resultado de la conversión tirado a la basura

Este es el error de quien cree que int() transforma la variable:

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'

La línea 2 llama a int(), que devuelve el número 17, y ese número no va a ningún lugar. La variable idade sigue apuntando al texto. La función devuelve un valor nuevo y no altera el antiguo. La corrección es guardar el resultado: idade = int(idade). Lo mismo vale para str(), float() y para casi todo método de texto.

El 53 en lugar del 8

Sin error, solo con el resultado equivocado: el programa pide dos números, suma y muestra 53 en lugar de 8. El error está en la falta de conversión, y como el programa corre sin quejarse, es el que más tarda en ser encontrado por quien está empezando. El diagnóstico más rápido es imprimir el tipo, print(type(a)), o el valor con comillas, print(repr(a)). Si aparece '5' entre comillas, es texto.

Convertir uno de los dos

Alguien recuerda convertir el primer valor y se olvida del segundo: int(a) + b. El resultado es el TypeError de la tabla de arriba, unsupported types for __add__: 'int', 'str'. El mensaje es correcto, pero no dice cuál de las dos variables es texto, y es común mirar la variable equivocada. Cuando el TypeError aparezca en una suma, comprueba el tipo de los dos lados.

El int() usado como round()

Quien convierte una nota 6.9 con int(6.9) y recibe 6 suele creer que Python se equivocó. La conversión cortó, como siempre hace. En cálculos de promedio, de descuento y de porcentaje, la elección entre cortar y redondear cambia el resultado final y tiene que ser una decisión, no un azar. Al escribir int(...) en una cuenta, conviene preguntarse si el "hacia abajo" es realmente lo que pide el problema.

Ejercicio: la cuenta del restaurante

Un restaurante cobra 10% de servicio. Escribe un programa que lea el valor de la cuenta como el usuario lo escribe, con coma, y muestre el total con el servicio, con dos decimales y con coma. Piensa primero en los pasos: leer el texto, cambiar la coma, convertir, multiplicar por 1,10, redondear y cambiar el punto de vuelta a coma.

texto = input("Valor de la cuenta: ")
valor = float(texto.replace(",", "."))
total = valor * 1.10
print("Total con 10%:", round(total, 2))
print("Total con 10%:", str(round(total, 2)).replace(".", ","))
centavos = round(valor * 100)
print(centavos, centavos * 110 // 100)

Con 47,90 de entrada, la salida es:

Valor de la cuenta: 47,90
Total con 10%: 52.69
Total con 10%: 52,69
4790 5269

La primera línea muestra el resultado con punto, que sirve para Python. La segunda convierte el número en texto, cambia el punto y muestra 52,69, como el usuario espera leer. Las dos últimas líneas hacen la misma cuenta en centavos enteros: round(valor * 100) da 4790, y 4790 * 110 // 100 da 5269. Fíjate en que el round() aparece de nuevo en la conversión a centavos, por el motivo de la sección anterior. Prueba con 47 (sin ninguna coma), con abc y con el campo vacío, para ver qué pasa en cada caso y comprobar si el programa hace lo que el usuario espera.

Preguntas frecuentes

¿Por qué int("3.5") da error y int(3.5) no?

Porque son dos entradas de naturaleza distinta. Con el número, el int() corta la parte decimal. Con el texto, intenta leer un entero escrito en dígitos, y el punto no es un dígito. Para convertir "3.5" en entero, pasa primero por float(): int(float("3.5")) da 3.

¿Necesito convertir para mostrar un número con print()?

No. El print() acepta cualquier tipo y convierte solo para mostrar. La conversión con str() solo es obligatoria cuando unes el número a un texto con el signo +.

¿Cómo mostrar un decimal con dos decimales?

Con la f-string: f"{x:.2f}". Para x = 52.69, muestra 52.69. El :.2f no altera el valor, solo la forma de mostrarlo. Si necesitas el valor redondeado para seguir calculando, usa round(x, 2).

¿El float() acepta la coma si cambio la configuración del computador?

No. Python no consulta la configuración regional para leer números. El punto es siempre el separador decimal en el código y en las conversiones, y el .replace() es la manera de lidiar con la entrada escrita con coma.

Para continuar

La ruta Lógica con Python tiene desafíos que exigen exactamente estas conversiones. El Suma de dos y el Doble de un número son el calentamiento con int(input()), el Promedio de notas junta conversión y división, y el Descuento del 10% exige cuidado con decimales. Si algún punto quedó suelto, relee el artículo sobre variables y tipos, que explica los cuatro tipos que aquí aparecen en movimiento, y el texto sobre operadores aritméticos.

El próximo tema de la serie abre el módulo de decisión: los operadores relacionales y lógicos, ==, <, and, or y not. Con ellos, el programa deja de repetir siempre la misma secuencia y pasa a elegir el camino según el valor que acaba de ser convertido.

Para practicar en PyPlaca

Rutas

Lecciones

Fichas de componentes

FastTeacherPara profesores

Del programa al semestre planificado

  • Plan de enseñanza y calendario montados solos
  • Diario de clases listo para pegar en el SIGA
  • Diapositivas y listas de ejercicios con solucionario
Conocer FastTeacher

Versión Community gratis · Windows

FastMindAsistente de IA local

La IA que recuerda tu vida y vive en tu ordenador

  • Memoria a largo plazo con la fuente de cada respuesta
  • Funciona sin conexión: tus datos se quedan en tu PC
  • Lee PDF, diapositivas, fotos y grabaciones de reuniones
Descargar gratis para Windows

Plan Esencial gratis para siempre

FastTeacherPara profesores

Del programa al semestre planificado

  • Plan de enseñanza y calendario montados solos
  • Diario de clases listo para pegar en el SIGA
  • Diapositivas y listas de ejercicios con solucionario
Conocer FastTeacher

Versión Community gratis · Windows