Python Medio · Teoría

Comprende antes de memorizar

22 lecciones originales con ejemplos breves, puntos clave y referencias para profundizar.

01

List comprehensions

Una list comprehension construye una lista declarando transformación, recorrido y filtros en una expresión legible.

Ejemplo
cuadrados = [n * n for n in range(6) if n % 2 == 0]

Puntos importantes

  • La expresión inicial produce cada elemento.
  • No fuerces lógica compleja dentro de una comprehension.
Practicar este concepto
02

Comprehensions de dict y set

Las comprehensions de diccionario generan pares clave-valor; las de conjunto eliminan duplicados según hash e igualdad.

Ejemplo
longitudes = {texto: len(texto) for texto in ["sol", "luna"]}
iniciales = {texto[0] for texto in ["sol", "senda"]}

Puntos importantes

  • Una dict comprehension necesita clave y valor.
  • Un set no conserva duplicados.
03

Funciones como valores y lambda

Las funciones son objetos: pueden asignarse, almacenarse en colecciones, recibirse como argumentos y devolverse. lambda crea una función anónima limitada a una expresión y resulta útil para criterios breves, no para ocultar lógica compleja.

Ejemplo
operaciones = [str.lower, lambda texto: texto.strip()]
resultado = operaciones[0]("PYTHON")

Puntos importantes

  • Pasa la función sin paréntesis cuando no quieras ejecutarla todavía.
  • Prefiere def si la operación necesita nombre, documentación o varias expresiones.
Practicar este concepto
04

Unpacking y starred expressions

El unpacking distribuye elementos de un iterable entre destinos. Un único nombre con * recoge la parte variable en una lista.

Ejemplo
primero, *centro, ultimo = [1, 2, 3, 4]
combinada = [0, *centro, 5]

Puntos importantes

  • La cantidad de destinos debe ser compatible.
  • * también expande iterables al construir colecciones.
05

Argumentos variables con *args

Un parámetro *args reúne argumentos posicionales restantes en una tupla. Permite adaptar una función sin perder el orden de llamada.

Ejemplo
def sumar(*valores):
    return sum(valores)

Puntos importantes

  • args es una convención; el asterisco define el comportamiento.
  • No reemplaza un contrato de parámetros claro.
Practicar este concepto
06

Argumentos nombrados con **kwargs

**kwargs reúne argumentos por palabra clave en un diccionario. Al llamar, ** expande un mapping con claves de texto válidas.

Ejemplo
def configurar(**opciones):
    return opciones.get("tema", "claro")

Puntos importantes

  • Las claves deben ser nombres de parámetro válidos.
  • Valida opciones desconocidas cuando el contrato sea cerrado.
07

map, filter, zip y enumerate

map transforma elementos de forma perezosa y filter conserva los que cumplen un predicado. zip recorre iterables en paralelo hasta que termina el más corto; enumerate añade posiciones sin gestionar un contador manual.

Ejemplo
nombres = ["Ada", "Lin"]
puntos = [8, 9]
filas = list(enumerate(zip(map(str.upper, nombres), puntos), start=1))

Puntos importantes

  • map, filter, zip y enumerate devuelven iteradores en Python 3.
  • Una comprehension suele ser más clara para una transformación sencilla; zip destaca al combinar recorridos.
Practicar este concepto
08

LEGB, global y nonlocal

Python busca nombres en los ámbitos local, enclosing, global y builtins. global permite reasignar un nombre del módulo y nonlocal reasigna uno del ámbito envolvente más cercano; ambas declaraciones deben usarse con moderación porque introducen estado compartido.

Ejemplo
total = 0
def registrar():
    global total
    total += 1

def contador():
    valor = 0
    def avanzar():
        nonlocal valor
        valor += 1
        return valor
    return avanzar

Puntos importantes

  • global apunta al ámbito del módulo; nonlocal, a una función envolvente.
  • Prefiere devolver valores y pasarlos como argumentos cuando no necesites estado compartido.
Practicar este concepto
09

Imports, módulos y paquetes

Cada módulo tiene su propio espacio de nombres. import modulo conserva visible el origen; from modulo import nombre enlaza un miembro concreto y los imports relativos se resuelven respecto del paquete actual.

Ejemplo
import math
from pathlib import Path
print(math.isqrt(81), Path("datos"))

Puntos importantes

  • Los módulos cargados se reutilizan desde sys.modules.
  • Evita from modulo import * y dependencias circulares entre módulos.
10

Clases e instancias

Una clase define cómo construir objetos y qué comportamiento comparten. self es la instancia receptora y se pasa de forma implícita al llamar un método.

Ejemplo
class Contador:
    def __init__(self, inicio=0):
        self.valor = inicio
    def avanzar(self):
        self.valor += 1
        return self.valor

Puntos importantes

  • __init__ inicializa una instancia ya creada.
  • Los atributos de instancia viven normalmente en __dict__.
Practicar este concepto
11

Atributos de clase e instancia

Un atributo de clase se comparte durante la búsqueda; asignar el mismo nombre en una instancia crea normalmente un atributo propio que lo sombrea.

Ejemplo
class Documento:
    categoria = "texto"

uno = Documento()
uno.categoria = "informe"

Puntos importantes

  • No guardes estado mutable por instancia en la clase.
  • type(objeto) accede a su clase.
12

Herencia y super

La herencia permite especializar comportamiento. super delega según el orden de resolución de métodos, no significa simplemente llamar al padre textual.

Ejemplo
class Mensaje:
    def texto(self): return "base"
class Alerta(Mensaje):
    def texto(self): return super().texto().upper()

Puntos importantes

  • Diseña una relación de sustitución real.
  • Prefiere composición para capacidades independientes.
13

Dataclasses

@dataclass genera métodos como __init__ y __repr__ a partir de campos anotados. field controla valores predeterminados y fábricas.

Ejemplo
from dataclasses import dataclass
@dataclass(frozen=True)
class Punto:
    x: int
    y: int

Puntos importantes

  • default_factory evita compartir mutables.
  • frozen limita asignaciones, pero no congela objetos anidados.
Practicar este concepto
14

Propiedades

property ofrece sintaxis de atributo con lógica de lectura o escritura. El almacenamiento debe usar otro nombre para evitar recursión.

Ejemplo
class Temperatura:
    def __init__(self, celsius): self._celsius = celsius
    @property
    def celsius(self): return self._celsius

Puntos importantes

  • Una propiedad mantiene una interfaz estable.
  • No ocultes operaciones costosas tras una lectura sorprendente.
17

Decoradores

Un decorador recibe el objeto definido y devuelve el objeto que quedará enlazado al nombre. functools.wraps conserva metadatos de la función envuelta.

Ejemplo
from functools import wraps
def registrar(funcion):
    @wraps(funcion)
    def wrapper(*args, **kwargs):
        return funcion(*args, **kwargs)
    return wrapper

Puntos importantes

  • @decorador se aplica al definir.
  • El wrapper debe respetar el contrato original.
Practicar este concepto
18

Context managers

with usa __enter__ y __exit__ para delimitar adquisición y liberación. La limpieza ocurre incluso si el bloque lanza una excepción.

Ejemplo
class Recurso:
    def __enter__(self): return self
    def __exit__(self, exc_type, exc, tb): return False

Puntos importantes

  • Devolver True desde __exit__ suprime la excepción.
  • La gestión del recurso queda junto a su uso.
19

Archivos y rutas seguras

pathlib representa rutas y open debe usarse con with. Especificar encoding evita depender de la configuración local; las rutas recibidas deben validarse contra una carpeta permitida.

Ejemplo
from pathlib import Path
ruta = Path("notas.txt")
with ruta.open("w", encoding="utf-8") as archivo:
    archivo.write("hola")

Puntos importantes

  • No concatenes rutas no confiables sin validarlas.
  • El sistema de archivos de Pyodide es virtual y efímero.
20

JSON

json.dumps serializa datos compatibles y json.loads analiza texto JSON. JSON no preserva tuplas, claves no textuales ni objetos arbitrarios.

Ejemplo
import json
texto = json.dumps({"activo": True})
dato = json.loads(texto)

Puntos importantes

  • Analizar JSON no ejecuta código.
  • Configura ensure_ascii según el contrato de salida.
Practicar este concepto
21

Anotaciones de tipo

Las anotaciones describen contratos para herramientas y lectores; Python no las impone automáticamente en runtime. Las uniones usan | y collections.abc contiene protocolos de uso común.

Ejemplo
from collections.abc import Iterable
def total(valores: Iterable[int]) -> int:
    return sum(valores)

Puntos importantes

  • Anota interfaces, no implementaciones innecesarias.
  • None | str representa un valor opcional.
22

Excepciones avanzadas y raise

raise crea o vuelve a propagar una excepción y raise ... from ... conserva una causa explícita. except puede manejar tipos concretos; else separa el camino correcto y finally garantiza limpieza, pero no debe ocultar un error con un return.

Ejemplo
def cargar_entero(texto):
    try:
        return int(texto)
    except ValueError as error:
        raise ValueError("formato de entero inválido") from error
    finally:
        print("intento finalizado")

Puntos importantes

  • Usa raise sin argumentos dentro de except para conservar el traceback original.
  • Encadena errores cuando traduzcas una excepción de bajo nivel al contrato de tu función.
Practicar este concepto