Entrada y salida en Python: print, input y f-strings
En esta lección
Casi todos los programas hacen lo mismo: reciben datos, los procesan y muestran un resultado. En Python, la salida por pantalla se hace con print() y la entrada por teclado con input(). Ya los usaste en la introducción; en esta lección los verás a fondo: todos los parámetros de print, cómo convertir y validar lo que escribe el usuario sin que el programa se rompa, y cómo dar formato profesional a números, tablas y fechas con las f-strings.
print a fondo
print acepta cualquier número de valores, de cualquier tipo, y los muestra separados por un espacio:
producto = "zapatillas"
talla = 42
precio = 59.9
print("Has elegido", producto, "talla", talla, "por", precio, "€")
# Has elegido zapatillas talla 42 por 59.9 €
No hace falta convertir los números a texto: print llama a str() sobre cada valor por ti. Esa es una diferencia importante con el operador +, que solo une textos.
sep: el separador entre valores
El parámetro sep (de separator) cambia lo que se pone entre los valores. Por defecto es un espacio:
print("05", "10", "2026", sep="/")
print("ana", "gmail.com", sep="@")
print("Pan", "Leche", "Huevos", sep="\n")
# 05/10/2026
# ana@gmail.com
# Pan
# Leche
# Huevos
Con sep="\n" cada valor sale en su línea. Y con el operador *, que reparte una lista en argumentos sueltos, puedes imprimir una lista entera con el separador que quieras:
ruta = ["Covadonga", "Lagos", "Vega de Ario", "Caín"]
print(*ruta, sep=" -> ")
# Covadonga -> Lagos -> Vega de Ario -> Caín
end: qué se escribe al final
Por defecto, cada print termina con un salto de línea ("\n"). El parámetro end lo sustituye por lo que quieras. Así puedes escribir varias cosas en la misma línea con varios print:
for vuelta in range(1, 6):
print(vuelta, end=" ")
print() # salto de línea final
print("Series completadas", end="!\n")
# 1 2 3 4 5
# Series completadas!
El print() vacío del medio solo escribe un salto de línea: sin él, el siguiente texto saldría pegado a los números.
file: a dónde va el texto
Normalmente print escribe en la salida estándar (sys.stdout), que es la pantalla. Con file puedes mandarlo a otro sitio. El caso más habitual es la salida de errores (sys.stderr), un canal separado para mensajes de error:
import sys
print("Procesando pedidos...")
print("Aviso: falta el código postal del pedido 17", file=sys.stderr)
# Procesando pedidos...
# Aviso: falta el código postal del pedido 17
En la terminal los dos mensajes se ven igual, pero son canales distintos: si rediriges la salida de tu programa a un fichero (python programa.py > informe.txt), los avisos de stderr seguirán apareciendo en pantalla. file también acepta un fichero abierto con open(), como verás en Ficheros.
flush: mostrar el texto ya
Python no siempre escribe en pantalla al instante: a veces acumula el texto en un búfer (una zona de memoria intermedia) y lo vuelca de golpe, porque es más rápido. Casi nunca lo notarás, pero en una barra de progreso que se escribe con end="" puede que no veas nada hasta el final. flush=True obliga a mostrarlo en el momento:
import time
print("Descargando", end="", flush=True)
for _ in range(3):
time.sleep(0.1)
print(".", end="", flush=True)
print(" hecho")
# Descargando... hecho
Nota:
None. Por esoresultado = print("hola")guardaNone, no el texto.return.
input: leer lo que escribe el usuario
input() muestra un mensaje, espera a que el usuario escriba algo y pulse Enter, y devuelve lo escrito como texto (str), sin el salto de línea final:
nombre = input("¿Cómo te llamas? ")
edad = input("¿Cuántos años tienes? ")
print(f"Hola, {nombre}. Tipo de edad: {type(edad).__name__}")
# ¿Cómo te llamas? Lucía
# ¿Cuántos años tienes? 19
# Hola, Lucía. Tipo de edad: str
Aunque el usuario escriba 19, edad es el texto "19". Si intentas sumarle 1 obtendrás TypeError. Hay que convertirlo con int() o float().
Nota:
input()necesita a alguien escribiendo en una terminal, así que en el editor de esta web no funciona igual. En el resto de la lección, los datos del usuario se simulan con variables de texto, para que puedas ejecutar todos los ejemplos. En tu ordenador, cambia esas variables porinput(...)y funcionará igual.
Convertir lo que llega como texto
Las funciones de conversión más usadas son int(), float() y str(). Además, conviene limpiar el texto antes de convertirlo:
respuesta = " 42 \n" # simula lo que podría llegar de input()
unidades = int(respuesta) # int ignora los espacios de los extremos
print(unidades * 2) # 84
precio_texto = "12,50" # en España se escribe la coma decimal
precio = float(precio_texto.replace(",", "."))
print(precio) # 12.5
confirmar = " SÍ "
print(confirmar.strip().lower() in ("sí", "si", "s")) # True
Tres trucos que usarás a menudo:
intyfloataceptan espacios al principio y al final, pero no letras ni la coma decimal..replace(",", ".")permite que el usuario escriba12,50como está acostumbrado..strip().lower()normaliza respuestas tipo sí/no, para no depender de mayúsculas ni espacios.
Varios datos en una línea
Si pides varios números a la vez (por ejemplo, "3 8 5"), sepáralos con split() y convierte cada trozo:
linea = "7.5 8 6.25" # simula input("Notas: ")
notas = [float(n) for n in linea.split()]
print(notas) # [7.5, 8.0, 6.25]
alto, ancho = map(int, "180 90".split()) # dos valores en dos variables
print(alto * ancho) # 16200
map(int, ...) aplica int a cada trozo. Si llegan más o menos valores de los esperados, el desempaquetado falla con ValueError.
Validar la entrada con try y except
¿Qué pasa si el usuario escribe "doce" cuando esperabas un número? int("doce") lanza un ValueError y, si no lo capturas, el programa se detiene. Con try/except (lo verás a fondo en Excepciones) puedes reaccionar al error:
def a_entero(texto):
"""Convierte un texto en entero o devuelve None si no es válido."""
try:
return int(texto)
except ValueError:
return None
for prueba in ["25", " 3 ", "doce", "4.5", ""]:
print(repr(prueba), "->", a_entero(prueba))
# '25' -> 25
# ' 3 ' -> 3
# 'doce' -> None
# '4.5' -> None
# '' -> None
Fíjate en que int("4.5") también falla: int solo acepta textos con números enteros. Si quieres admitir decimales, usa float.
Repetir la pregunta hasta que sea válida
En un programa real con teclado, lo habitual es preguntar en bucle hasta recibir un dato correcto. Este es el patrón clásico (pruébalo en tu ordenador):
while True:
texto = input("Edad (0-120): ")
try:
edad = int(texto)
except ValueError:
print("Escribe un número entero, por favor.")
continue
if 0 <= edad <= 120:
break
print("La edad debe estar entre 0 y 120.")
print(f"Edad registrada: {edad}")
# Edad (0-120): veinte
# Escribe un número entero, por favor.
# Edad (0-120): 200
# La edad debe estar entre 0 y 120.
# Edad (0-120): 20
# Edad registrada: 20
Hay dos comprobaciones distintas: que el texto sea un número (try/except) y que el número tenga sentido (el if del rango). continue vuelve al principio del bucle y break lo termina cuando todo es correcto.
Para no depender del teclado, aquí tienes la misma lógica en una función que recibe las respuestas en una lista, como si el usuario las hubiera escrito una tras otra:
def pedir_edad(respuestas):
for texto in respuestas:
try:
edad = int(texto)
except ValueError:
print(f"'{texto}' no es un número")
continue
if 0 <= edad <= 120:
return edad
print(f"{edad} está fuera de rango")
return None
print("Edad:", pedir_edad(["veinte", "200", "20"]))
# 'veinte' no es un número
# 200 está fuera de rango
# Edad: 20
Consejo: separar la lógica (validar un texto) de la entrada (
input) hace tu código más fácil de probar. Es la misma idea que usarás más adelante con las pruebas automáticas.
f-strings a fondo
Una f-string es un texto con una f delante en el que puedes meter cualquier expresión entre llaves. Ya conoces lo básico de Variables y tipos; ahora veamos todo lo que admite el formato, que va después de dos puntos:
{valor:[relleno][alineación][signo][ancho][,][.precisión][tipo]}
No hace falta aprenderlo de memoria: basta con conocer las piezas más útiles.
Decimales, miles y signo
total = 1234567.891
print(f"{total:.2f}") # 1234567.89
print(f"{total:,.2f}") # 1,234,567.89
print(f"{total:_.0f}") # 1_234_568
print(f"{3:+d} {-3:+d}") # +3 -3
print(f"{0.000123:.2e}") # 1.23e-04
.2f: número decimal (float) con 2 cifras tras el punto. Redondea, no corta.,o_: separador de miles.+: muestra siempre el signo, útil para variaciones (“+3 puntos”).e: notación científica.
El separador de miles sigue el estilo inglés (coma para miles, punto para decimales). Para el formato español, intercambia los símbolos:
def euros(cantidad):
texto = f"{cantidad:,.2f}" # 1,234,567.89
texto = texto.replace(",", "X").replace(".", ",").replace("X", ".")
return texto + " €"
print(euros(1234567.891)) # 1.234.567,89 €
print(euros(9.5)) # 9,50 €
Ancho y alineación
Indicas un ancho mínimo y cómo alinear dentro de él: < izquierda, > derecha, ^ centro. Delante puedes poner un carácter de relleno:
print(f"[{'Ana':<8}]") # [Ana ]
print(f"[{'Ana':>8}]") # [ Ana]
print(f"[{'Ana':^8}]") # [ Ana ]
print(f"[{'Ana':*^9}]") # [***Ana***]
print(f"[{42:>6}]") # [ 42]
print(f"{' MENÚ ':=^24}") # ========= MENÚ =========
Los textos se alinean a la izquierda por defecto y los números a la derecha. El ancho también puede venir de una variable, metiendo otras llaves dentro del formato:
ancho = 12
print(f"|{'centrado':^{ancho}}|") # | centrado |
Ceros a la izquierda y otras bases
pedido = 7
print(f"PED-{pedido:05d}") # PED-00007
print(f"{9:02d}:{5:02d}") # 09:05
print(f"{255:b} {255:x} {255:X} {255:o}") # 11111111 ff FF 377
print(f"#{255:02x}{128:02x}{0:02x}") # #ff8000
05d significa “entero (d) de ancho 5 rellenado con ceros”. Es lo que usarías para números de factura, horas o códigos. b, x y o muestran el número en binario, hexadecimal y octal; el último ejemplo construye un color CSS.
Porcentajes
El tipo % multiplica por 100 y añade el símbolo:
aprobados = 23
alumnos = 28
print(f"Aprobados: {aprobados / alumnos:.1%}") # Aprobados: 82.1%
print(f"Descuento: {0.15:.0%}") # Descuento: 15%
Así no tienes que multiplicar por 100 a mano: le pasas la proporción (un número entre 0 y 1) y el formato hace el resto.
Fechas
Los objetos de fecha del módulo datetime aceptan los códigos de strftime directamente en la f-string:
from datetime import datetime
cita = datetime(2026, 10, 5, 9, 30)
print(f"{cita:%d/%m/%Y}") # 05/10/2026
print(f"{cita:%H:%M}") # 09:30
print(f"{cita:%d/%m/%Y a las %H:%M}") # 05/10/2026 a las 09:30
%d es el día, %m el mes, %Y el año con cuatro cifras, %H la hora y %M los minutos. Tienes la lista completa en Fechas.
= para depurar
Si pones = justo después de la expresión, la f-string muestra el texto de la expresión y su valor. Es la forma más rápida de comprobar qué vale algo mientras programas:
precio = 19.99
unidades = 3
print(f"{precio=}, {unidades=}")
print(f"{precio * unidades = :.2f}")
# precio=19.99, unidades=3
# precio * unidades = 59.97
Se puede combinar con un formato después de los dos puntos, como en la segunda línea.
!r, llaves literales y textos largos
ciudad = "Santander"
print(f"Ciudad: {ciudad!r}") # Ciudad: 'Santander'
print(f"Usa {{nombre}} en la plantilla") # Usa {nombre} en la plantilla
mensaje = (
f"Pedido de {ciudad}: "
f"{unidades} unidades, "
f"total {precio * unidades:.2f} €"
)
print(mensaje)
# Pedido de Santander: 3 unidades, total 59.97 €
!rmuestra el valor conrepr(), con comillas. Viene bien para ver espacios ocultos en un texto.- Para escribir una llave de verdad, duplícala:
{{y}}. - Varias f-strings seguidas dentro de paréntesis se unen solas: es la forma limpia de partir un texto largo.
Ejemplo completo: un ticket de compra
Juntamos todo: alineación, decimales, ancho y repetición de caracteres.
cesta = [
("Manzanas (kg)", 2.5, 1.89),
("Pan integral", 1, 1.35),
("Aceite de oliva", 1, 9.75),
("Yogures", 8, 0.42),
]
ANCHO = 38
print(f"{'FRUTERÍA LA HUERTA':^{ANCHO}}")
print("-" * ANCHO)
print(f"{'Producto':<18}{'Cant.':>6}{'Importe':>14}")
total = 0
for nombre, cantidad, precio in cesta:
importe = cantidad * precio
total += importe
print(f"{nombre:<18}{cantidad:>6g}{importe:>12.2f} €")
print("-" * ANCHO)
print(f"{'TOTAL':<24}{total:>12.2f} €")
print(f"{'IVA incluido (10 %)':<24}{total - total / 1.10:>12.2f} €")
# FRUTERÍA LA HUERTA
# --------------------------------------
# Producto Cant. Importe
# Manzanas (kg) 2.5 4.72 €
# Pan integral 1 1.35 €
# Aceite de oliva 1 9.75 €
# Yogures 8 3.36 €
# --------------------------------------
# TOTAL 19.18 €
# IVA incluido (10 %) 1.74 €
El tipo g muestra el número de la forma más corta: 2.5 se queda igual y 1 no se convierte en 1.0.
Las formas antiguas: str.format y %
Las f-strings existen desde Python 3.6. Antes se usaban otras dos formas que verás en código antiguo y en muchos tutoriales. Usan el mismo mini lenguaje de formato:
nombre = "Marta"
saldo = 1520.5
print("Hola, {}. Tu saldo es {:.2f} €".format(nombre, saldo))
print("Hola, {n}. Tu saldo es {s:,.2f} €".format(n=nombre, s=saldo))
print("Hola, %s. Tu saldo es %.2f €" % (nombre, saldo))
# Hola, Marta. Tu saldo es 1520.50 €
# Hola, Marta. Tu saldo es 1,520.50 €
# Hola, Marta. Tu saldo es 1520.50 €
str.formatsustituye cada{}por los argumentos, en orden o por nombre. Todavía es útil cuando la plantilla se define antes de tener los datos, por ejemplo guardada en una constante.- El operador
%es el estilo de C:%spara texto,%dpara enteros y%.2fpara decimales. Hoy solo lo encontrarás en código antiguo y en el módulologging.
PLANTILLA = "Reserva de {cliente} para {personas} personas"
print(PLANTILLA.format(cliente="Iñaki", personas=4))
# Reserva de Iñaki para 4 personas
Para todo lo demás, usa f-strings: son más cortas, más rápidas y se leen mejor.
Errores frecuentes
- Operar con lo que devuelve
inputsin convertirlo:input("Edad: ") + 1daTypeError: can only concatenate str (not "int") to str. Convierte conint()ofloat(). - Convertir sin validar:
int("12,5")oint("")lanzanValueErrory paran el programa. Envuelve la conversión entry/except. - Olvidar la
f:"Total: {total}"imprime las llaves tal cual. Comprueba que el texto empieza porf". - Confundir
sepyend:sepva entre valores del mismoprint;end, al final de cadaprint. - Usar
+para unir textos y números:"Tienes " + 3 + " avisos"falla. Usa una f-string oprintcon comas. - Esperar formato español con
:,: el separador de miles es la coma inglesa. Cámbialo conreplacesi necesitas1.234,50. - Guardar el resultado de
print: devuelveNone. Para construir un texto y guardarlo, usa una f-string.
Resumen
| Herramienta | Para qué sirve | Ejemplo |
|---|---|---|
sep | Separador entre valores | print(d, m, a, sep="/") |
end | Final de cada print | print(x, end=" ") |
file | Destino de la salida | print(msg, file=sys.stderr) |
flush | Mostrar sin esperar al búfer | print(".", end="", flush=True) |
input() | Leer texto del teclado | nombre = input("Nombre: ") |
int() / float() | Convertir texto en número | int(texto) |
try/except ValueError | Validar la conversión | Repetir la pregunta en un bucle |
:.2f / :, | Decimales / miles | f"{x:,.2f}" |
:<10 :>10 :^10 | Alinear en un ancho | f"{nombre:<18}" |
:05d | Ceros a la izquierda | f"{7:05d}" -> 00007 |
:.1% | Porcentaje | f"{0.821:.1%}" |
:%d/%m/%Y | Formato de fecha | f"{hoy:%d/%m/%Y}" |
{x=} | Depurar: nombre y valor | f"{precio=}" |
.format() / % | Formas antiguas | "{}".format(x) |
En la siguiente lección harás que tus programas tomen decisiones con if, elif y else.
Pon a prueba lo que has aprendido
¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.