Python se lee casi como inglés y tiene bibliotecas para todo, por eso es uno de los lenguajes más recomendados para empezar. Se usa para automatizar tareas repetitivas, analizar datos, crear webs y en casi todo lo relacionado con la inteligencia artificial.
Automatizar tareas y scripts
Análisis de datos e inteligencia artificial
Webs y APIs
Para empezar: Instala Python desde python.org, abre la terminal y escribe python (o py en Windows) para probar los ejemplos.
Nivel 1 Básico
1
Lección 1 · Básico
Tu primer programa
Python se ejecuta con un intérprete: lee tu código línea a línea y lo ejecuta. Puedes escribir órdenes directamente en él o guardarlas en un archivo .py y ejecutarlo con python archivo.py.
print() muestra en pantalla lo que le pases. Los comentarios empiezan por #.
Respuesta:print. print() escribe en la salida lo que pongas entre paréntesis.
2
Lección 2 · Básico
Variables, tipos y texto
Una variable se crea al darle un valor con =; no hace falta declarar su tipo. Los tipos básicos son int (enteros), float (decimales), str (texto) y bool (True o False).
input() pide un texto a la persona y siempre devuelve str: para hacer cuentas, conviértelo con int() o float(). Las cadenas f (f"…{variable}…") meten valores dentro de un texto.
Ejemplo práctico
nombre = input("¿Cómo te llamas? ")
edad = int(input("¿Cuántos años tienes? "))
print(f"Hola, {nombre}. El año que viene tendrás {edad + 1}.")
print(type(edad)) # <class 'int'>
Ejercicio
¿Qué tipo de dato devuelve siempre input()?
Ver la solución
Respuesta: str. input() devuelve texto (str); para operar con números hay que convertirlo.
3
Lección 3 · Básico
Condiciones y sangría
if, elif y else deciden qué bloque se ejecuta. En Python los bloques no van entre llaves: se marcan con dos puntos al final de la línea y con sangría (4 espacios) en las de dentro.
Si la sangría no es coherente, Python da un error. Es una regla del lenguaje, no una cuestión de estilo.
Ejemplo práctico
nota = 7.5
if nota >= 9:
print("Sobresaliente")
elif nota >= 5:
print("Aprobado")
else:
print("Suspenso")
# Muestra: Aprobado
Ejercicio
¿Cómo marca Python qué líneas van dentro de un if?
Ver la solución
Respuesta: Con la sangría. Las líneas del bloque van sangradas (normalmente 4 espacios) tras los dos puntos.
Encuentra los errores
Este programa debería decir «Sobresaliente» con un 9 o más, «Aprobado» con un 5 o más y «Suspenso» con menos. Python lo rechaza por 2 errores: márcalos.
Los errores
Línea 3: Las líneas con if, elif y else terminan con dos puntos :. Corrección: if nota >= 9:
Línea 6: El bloque del elif tiene que ir con sangría (4 espacios); si no, Python da IndentationError. Corrección: print("Aprobado")
Con los dos arreglos, el programa muestra «Aprobado» para una nota de 7.
Ver la solución
Línea 3: Las líneas con if, elif y else terminan con dos puntos :. Corrección: if nota >= 9:
Línea 6: El bloque del elif tiene que ir con sangría (4 espacios); si no, Python da IndentationError. Corrección: print("Aprobado")
4
Lección 4 · Básico
Listas y bucles
Una lista guarda varios valores en orden entre corchetes; la primera posición es la 0. Con append() añades al final y len() te dice cuántos elementos tiene.
for recorre cada elemento de una lista, y range(n) genera los números de 0 a n−1 cuando necesitas repetir algo un número fijo de veces.
Ejemplo práctico
compra = ["pan", "leche"]
compra.append("huevos")
print(len(compra)) # 3
for producto in compra:
print("- " + producto)
for i in range(3):
print(i) # 0, 1 y 2
Ejercicio
¿Qué números genera range(3)?
Ver la solución
Respuesta: 0, 1, 2. range(n) empieza en 0 y se detiene antes de n.
Escribe el código
Escribe la función contar_mayores(numeros, limite): devuelve cuántos números de la lista son mayores que limite. Usa un bucle for y un contador.
Tab escribe una sangría; para salir del editor con el teclado, pulsa Esc y luego Tab. Ctrl + Intro corrige.
Una solución posible
def contar_mayores(numeros, limite):
contador = 0
for n in numeros:
if n > limite:
contador += 1
return contador
El contador empieza en 0 y sube cada vez que un número supera el límite. «Mayor que» excluye el propio límite: con 5, el 5 no cuenta.
Ver la solución
def contar_mayores(numeros, limite):
contador = 0
for n in numeros:
if n > limite:
contador += 1
return contador
El contador empieza en 0 y sube cada vez que un número supera el límite. «Mayor que» excluye el propio límite: con 5, el 5 no cuenta.
Nivel 2 Intermedio
5
Lección 5 · Intermedio
Funciones
Con def defines una función: un nombre, sus parámetros entre paréntesis y el bloque sangrado. return devuelve el resultado.
Los parámetros pueden tener un valor por defecto, que se usa si no lo pasas al llamar a la función.
Respuesta:def. Las funciones se definen con def nombre(parámetros):.
Escribe el código
Escribe es_palindromo(texto): devuelve True si el texto se lee igual del derecho y del revés, sin tener en cuenta los espacios ni las mayúsculas («Ana», «Anita lava la tina»), y False si no.
Tab escribe una sangría; para salir del editor con el teclado, pulsa Esc y luego Tab. Ctrl + Intro corrige.
replace(" ", "") quita los espacios, lower() pasa todo a minúsculas y [::-1] le da la vuelta al texto. Si coincide con el original, es un palíndromo.
6
Lección 6 · Intermedio
Diccionarios
Un diccionario guarda pares clave–valor entre llaves: perfecto para describir algo con varios datos o para contar cosas. Accedes a un valor con su clave entre corchetes.
.get(clave, por_defecto) evita el error si la clave no existe, e .items() recorre las parejas.
Ejemplo práctico
stock = {"teclado": 10, "raton": 0}
stock["monitor"] = 3
print(stock["teclado"]) # 10
print(stock.get("webcam", 0)) # 0, sin error
for producto, unidades in stock.items():
print(producto, unidades)
Ejercicio
¿Qué pasa con stock["webcam"] si esa clave no existe?
Ver la solución
Respuesta: Da un error KeyError. Con corchetes, una clave inexistente lanza KeyError; con .get() puedes dar un valor por defecto.
Encuentra los errores
Este programa guarda el stock de una frutería y debería mostrar True y después False. Tiene 2 errores.
Los errores
Línea 4:stock[producto] da KeyError si el producto no está en el diccionario, como los kiwis. get() devuelve un valor por defecto. Corrección: return stock.get(producto, 0) > 0
Línea 6:== compara y descarta el resultado; para añadir la clave hay que asignar con un solo =. Corrección: stock["platanos"] = 12
stock.get(clave, 0) es la forma habitual de leer una clave que quizá no exista.
Ver la solución
Línea 4:stock[producto] da KeyError si el producto no está en el diccionario, como los kiwis. get() devuelve un valor por defecto. Corrección: return stock.get(producto, 0) > 0
Línea 6:== compara y descarta el resultado; para añadir la clave hay que asignar con un solo =. Corrección: stock["platanos"] = 12
7
Lección 7 · Intermedio
Archivos y errores
open() abre un archivo; dentro de un bloque with, Python lo cierra solo al terminar, aunque haya un error. Indica siempre la codificación utf-8 para que las tildes se lean bien.
Los errores en tiempo de ejecución son excepciones. Con try y except las capturas y decides qué hacer en lugar de que el programa se detenga.
Ejemplo práctico
try:
with open("notas.txt", encoding="utf-8") as f:
for linea in f:
print(linea.strip())
except FileNotFoundError:
print("No encuentro notas.txt")
Ejercicio
¿Qué ventaja tiene abrir un archivo con with?
Ver la solución
Respuesta: El archivo se cierra solo al terminar. with garantiza que el archivo se cierra al salir del bloque, también si ocurre un error.
Nivel 3 Avanzado
8
Lección 8 · Avanzado
Módulos, pip y entornos virtuales
Python trae una gran biblioteca estándar que usas con import. Para todo lo demás está PyPI, el repositorio de paquetes, y pip, que los instala.
Crea un entorno virtual por proyecto (python -m venv .venv) para que cada uno tenga sus propias versiones de bibliotecas y no choquen entre sí.
Ejemplo práctico
# En la terminal
python -m venv .venv
# Windows: .venv\Scripts\activate
# macOS/Linux: source .venv/bin/activate
pip install requests
# En tu programa
import json
from datetime import date
print(date.today().isoformat())
print(json.dumps({"ok": True}))
Ejercicio
Completa el comando que instala un paquete de PyPI.
install requests
Ver la solución
Respuesta:pip. pip install paquete descarga e instala una biblioteca en el entorno activo.
9
Lección 9 · Avanzado
Clases y objetos
Una clase es un molde para crear objetos que tienen datos (atributos) y acciones (métodos). __init__ se ejecuta al crear cada objeto y self es el propio objeto.
Las clases ayudan a ordenar programas grandes agrupando los datos con el código que trabaja con ellos.
Ejemplo práctico
class Cuenta:
def __init__(self, titular, saldo=0):
self.titular = titular
self.saldo = saldo
def ingresar(self, cantidad):
if cantidad <= 0:
raise ValueError("La cantidad debe ser positiva")
self.saldo += cantidad
cuenta = Cuenta("Ana")
cuenta.ingresar(50)
print(cuenta.saldo) # 50
Ejercicio
¿Qué método se ejecuta automáticamente al crear un objeto?
Ver la solución
Respuesta: __init__. __init__ prepara el objeto nuevo: normalmente guarda los valores iniciales en self.
10
Lección 10 · Avanzado
Comprensiones y anotaciones de tipo
Una lista por comprensión crea una lista nueva a partir de otra en una sola línea: [expresión for x in lista if condición].
Las anotaciones de tipo (precio: float) documentan qué espera y devuelve cada función. Python no las comprueba al ejecutar, pero el editor y herramientas como mypy sí te avisan de errores.
Ejemplo práctico
precios = [3.5, 12.0, 0.99, 25.0]
caros = [p for p in precios if p > 10]
print(caros) # [12.0, 25.0]
def media(valores: list[float]) -> float:
return sum(valores) / len(valores)
print(media(precios)) # 10.3725
Ejercicio
¿Qué devuelve [n * 2 for n in [1, 2, 3]]?
Ver la solución
Respuesta: [2, 4, 6]. La comprensión aplica n * 2 a cada elemento y junta los resultados en una lista nueva.
11
Lección 11 · Avanzado
Lanzar tus propios errores con raise
Además de capturar errores con try y except, puedes lanzarlos con raise cuando una función recibe algo que no tiene sentido. Así el fallo aparece en el momento y en el sitio donde ocurre, en lugar de arrastrar un dato erróneo.
Para errores propios de tu programa, crea una clase que herede de Exception. Quien llame a la función puede capturar justo ese tipo de error y darle un mensaje claro a la persona.
Ejemplo práctico
class SaldoInsuficiente(Exception):
pass
def retirar(saldo, cantidad):
if cantidad <= 0:
raise ValueError("La cantidad tiene que ser positiva")
if cantidad > saldo:
raise SaldoInsuficiente(f"Faltan {cantidad - saldo} €")
return saldo - cantidad
print(retirar(100, 30)) # 70
try:
retirar(100, 150)
except SaldoInsuficiente as error:
print("No se puede retirar:", error) # No se puede retirar: Faltan 50 €
Escribe el código
Escribe leer_edad(texto): convierte el texto en un número entero y lo devuelve. Si el número es negativo o mayor que 130, lanza un ValueError con raise. (Si el texto no es un número, int() ya lanza ValueError por sí solo.)
Tab escribe una sangría; para salir del editor con el teclado, pulsa Esc y luego Tab. Ctrl + Intro corrige.
Una solución posible
def leer_edad(texto):
edad = int(texto)
if edad < 0 or edad > 130:
raise ValueError("Edad fuera de rango")
return edad
int(texto) convierte el texto; después se comprueba el rango y, si no es válido, raise ValueError(...) detiene la función con ese error.
Ver la solución
def leer_edad(texto):
edad = int(texto)
if edad < 0 or edad > 130:
raise ValueError("Edad fuera de rango")
return edad
int(texto) convierte el texto; después se comprueba el rango y, si no es válido, raise ValueError(...) detiene la función con ese error.
12
Lección 12 · Avanzado
Datos en JSON y CSV
JSON y CSV son los formatos más habituales para guardar e intercambiar datos. El módulo json convierte diccionarios y listas en texto JSON (json.dumps) y al revés (json.loads); json.dump y json.load hacen lo mismo directamente con un archivo.
El módulo csv lee y escribe tablas separadas por comas, como las que abre una hoja de cálculo. csv.DictReader devuelve cada fila como un diccionario cuyas claves son los títulos de la primera fila. Abre los archivos con encoding="utf-8" para que las tildes se lean bien.
Ejemplo práctico
import csv
import json
with open("gastos.csv", "w", newline="", encoding="utf-8") as f:
f.write("concepto,importe\nLuz,45.20\nAgua,18.75\nInternet,30\n")
with open("gastos.csv", newline="", encoding="utf-8") as f:
filas = list(csv.DictReader(f))
total = sum(float(fila["importe"]) for fila in filas)
print(f"{len(filas)} gastos, total: {total:.2f} €") # 3 gastos, total: 93.95 €
resumen = {"gastos": len(filas), "total": round(total, 2)}
print(json.dumps(resumen)) # {"gastos": 3, "total": 93.95}
Ejercicio
Completa para convertir el texto JSON en un diccionario de Python.
datos = json.('{"nombre": "Ana"}')
Ver la solución
Respuesta:loads. json.loads() convierte un texto JSON en diccionarios y listas de Python; json.dumps() hace lo contrario.
13
Lección 13 · Avanzado
Fechas y horas con datetime
El módulo datetime representa fechas (date), fechas con hora (datetime) y duraciones (timedelta). Restar dos fechas da un timedelta, y sumar un timedelta a una fecha la mueve hacia delante o hacia atrás.
strftime convierte una fecha en texto con el formato que quieras (%d/%m/%Y es día/mes/año) y strptime hace lo contrario: lee un texto con ese formato y lo convierte en fecha.
Ejemplo práctico
from datetime import date, datetime, timedelta
inicio = date(2026, 1, 15)
fin = date(2026, 3, 1)
print((fin - inicio).days) # 45
entrega = inicio + timedelta(days=30)
print(entrega.strftime("%d/%m/%Y")) # 14/02/2026
cita = datetime.strptime("25/12/2026 18:30", "%d/%m/%Y %H:%M")
print(cita.year, cita.hour, cita.minute) # 2026 18 30
print(cita.weekday()) # 4 (lunes es 0: es viernes)
Respuesta: Un timedelta de 28 días. Restar dos fechas da un timedelta (una duración); su atributo .days vale 28, porque febrero de 2026 tiene 28 días.
14
Lección 14 · Avanzado
Generadores: valores de uno en uno con yield
Una función con yield es un generador: en lugar de devolver todos los resultados de golpe en una lista, entrega un valor cada vez que se le pide y se queda en pausa hasta el siguiente. Se recorre con for igual que una lista.
Como no guarda todos los valores a la vez, un generador puede recorrer archivos enormes o secuencias muy largas usando muy poca memoria. Si necesitas la lista completa, list(generador) la crea.
Ejemplo práctico
def cuenta_atras(desde):
while desde > 0:
yield desde
desde -= 1
for n in cuenta_atras(3):
print(n) # 3, 2 y 1, cada uno en una línea
def lineas_largas(lineas, minimo):
for linea in lineas:
if len(linea) >= minimo:
yield linea.strip()
texto = ["hola\n", "esta línea es larga\n", "fin\n"]
print(list(lineas_largas(texto, 10))) # ['esta línea es larga']
Escribe el código
Escribe el generador pares(limite): entrega con yield, uno a uno, los números pares desde 0 hasta limite sin incluirlo.
Tab escribe una sangría; para salir del editor con el teclado, pulsa Esc y luego Tab. Ctrl + Intro corrige.
Una solución posible
def pares(limite):
n = 0
while n < limite:
yield n
n += 2
Con while o con range(0, limite, 2), cada yield entrega un número y la función continúa por donde iba la siguiente vez.
Ver la solución
def pares(limite):
n = 0
while n < limite:
yield n
n += 2
Con while o con range(0, limite, 2), cada yield entrega un número y la función continúa por donde iba la siguiente vez.
15
Lección 15 · Avanzado
Pruebas automáticas con unittest
Una prueba automática es código que comprueba que otro código hace lo que debe. Si cambias algo y rompes una función, la prueba falla y te avisa antes de que lo note nadie. Python trae el módulo unittest para escribirlas.
Cada prueba es un método que empieza por test dentro de una clase que hereda de unittest.TestCase, y usa comprobaciones como assertEqual o assertRaises. Se ejecutan todas con python -m unittest.
Ejemplo práctico
import unittest
def precio_final(precio, descuento):
if not 0 <= descuento <= 100:
raise ValueError("El descuento va de 0 a 100")
return round(precio * (1 - descuento / 100), 2)
class PruebasPrecio(unittest.TestCase):
def test_sin_descuento(self):
self.assertEqual(precio_final(50, 0), 50)
def test_con_descuento(self):
self.assertEqual(precio_final(80, 25), 60)
def test_descuento_imposible(self):
with self.assertRaises(ValueError):
precio_final(10, 120)
if __name__ == "__main__":
unittest.main() # Ran 3 tests ... OK
Encuentra los errores
Estas pruebas deberían comprobar es_par(n), pero tienen 2 errores: una no se ejecutaría nunca y otra espera un resultado equivocado.
Los errores
Línea 10:unittest solo ejecuta los métodos cuyo nombre empieza por test; este se ignoraría sin avisar. Corrección: def test_siete(self):
Línea 14: 0 es par (0 % 2 vale 0), así que es_par(0) devuelve True y la prueba fallaría aunque la función esté bien. Corrección: self.assertEqual(es_par(0), True)
Una prueba mal escrita es tan peligrosa como un error en el código: conviene ver fallar cada prueba al menos una vez para saber que comprueba algo.
Ver la solución
Línea 10:unittest solo ejecuta los métodos cuyo nombre empieza por test; este se ignoraría sin avisar. Corrección: def test_siete(self):
Línea 14: 0 es par (0 % 2 vale 0), así que es_par(0) devuelve True y la prueba fallaría aunque la función esté bien. Corrección: self.assertEqual(es_par(0), True)
¿Has terminado? Sigue practicando
Repasa los conceptos en el diccionario, practica con estas herramientas o prueba otro lenguaje: las ideas que has aprendido (variables, condiciones, funciones, objetos…) te servirán en cualquiera.
* Porcentaje de personas que dijeron haber usado Python en la Stack Overflow Developer Survey 2026: Technology (pregunta sobre lenguajes de programación, de scripts y de marcado; todas las respuestas). El progreso de las lecciones se guarda solo en este navegador.
¿Nos dejas medir las visitas?
Con tu permiso usamos Google Analytics, que guarda cookies, para saber cuántas personas visitan la web y qué páginas les resultan útiles. No usamos cookies de publicidad y tus archivos nunca salen de tu navegador. Puedes cambiar de opinión cuando quieras en «Configurar cookies», al pie de la página. Más información.