Python Intermedio POO en práctica: el código y los comandos que realmente importan

Python Intermedio POO: lo esencial en un artículo — código real, diagramas y pasos concretos, extractos de un curso de 36 lecciones.

Python Intermedio POO en práctica: el código y los comandos que realmente importan

Ni teoría interminable aquí: abrimos la terminal y practicamos. Aquí tienes lo esencial de Python Intermedio POO, extraído directamente de un curso completo de 36 lecciones —con código real que puedes copiar y pegar ahora mismo.

tl;dr
  • Introducción e Instalación
  • Repaso de Python
  • Funciones avanzadas y lambdas
  • Clases y objetos
  • Herencia y polimorfismo
~$ cat ./parcours.md # Python Intermédiaire POO — 10 capítulos
01
Introducción e Instalación
→ Presentación del curso→ Instalar Python, VS Code y un entorno virtual+ 1 más lecciones
02
Repaso de Python
→ Variables, tipos y estructuras de datos esenciales→ Condiciones, bucles y comprensiones de lista+ 1 más lecciones
03
Funciones avanzadas y lambdas
→ Lambda, map, filter, reduce→ *args, **kwargs y argumentos por defecto+ 1 más lecciones
04
Clases y objetos
→ ¿Por qué la POO? Clases vs instancias→ Definir una clase: __init__, atributos y métodos+ 2 más lecciones
05
Herencia y polimorfismo
→ Herencia simple→ Herencia múltiple y MRO+ 1 más lecciones
06
Métodos especiales dunder
→ __str__, __repr__, __len__→ Operadores sobrecargados: __add__, __eq__, __lt__+ 1 más lecciones
07
Módulos y paquetes
→ Import, módulos y namespaces→ Crear su propio paquete con __init__.py+ 1 más lecciones
08
Gestión de errores y excepciones
→ try, except, else, finally→ Excepciones personalizadas+ 1 más lecciones
🏁
Proyecto final (+ 2 capítulos en camino)
→ Te vas con un proyecto concreto y demostrable

Encapsulación, properties y setters

NOTEObjetivo — Aprender a proteger los atributos internos de un objeto y a validar su modificación gracias a las properties, sin sobrecargar la interfaz pública.

Objetivos pedagógicos

TIPAl finalizar este módulo — Sabrás usar las convenciones _x y __x, convertir un atributo en property para añadir validación, y saber cuándo hacerlo.

¿Qué es la encapsulación?

La encapsulación consiste en ocultar los detalles internos de una clase y exponer solo una interfaz controlada.

NOTEAnalogía — Un mando a distancia de TV: pulsas «subir volumen» sin saber qué ocurre dentro de los circuitos. La interfaz es sencilla, lo interno está protegido.

Convenciones de Python

Python no fuerza la confidencialidad (a diferencia de Java). Utiliza convenciones basadas en el nombre.

ConvenciónSignificadoEfecto real
nomPúblicoAcceso libre, forma parte de la API
_nomProtegido (convención)«No tocar, salvo que sepas lo que haces»
__nomPrivado (name mangling)Renombrado a _NomClasse__nom
nom_Evita colisión con palabra claveEj.: class_ en lugar de class
output
class CompteBancaire:
    def __init__(self, titulaire, solde):
        self.titulaire = titulaire        # public
        self._solde = solde               # convention : ne pas toucher
        self.__pin = "1234"                # privé (name mangling)

c = CompteBancaire("Alice", 1000)
print(c.titulaire)                  # OK
print(c._solde)                     # accessible mais déconseillé
# print(c.__pin)                    # AttributeError !
print(c._CompteBancaire__pin)       # accessible avec le nom manglé
WARNINGEl __ no es una seguridad — Es un mecanismo para evitar colisiones accidentales en la herencia. Para una seguridad real, utiliza permisos a nivel de sistema.

El problema sin encapsulación

output
class Temperature:
    def __init__(self, celsius):
        self.celsius = celsius

t = Temperature(25)
t.celsius = -500          # absurde !
print(t.celsius)          # -500

No hay validación. El -500 es imposible (cero absoluto = -273,15), pero Python lo acepta.

@property: convertir un atributo en método

Un @property hace que una llamada como obj.attribut ejecute en realidad un método, sin cambiar la sintaxis de uso.

output
class Temperature:
    def __init__(self, celsius):
        self._celsius = celsius

    @property
    def celsius(self):
        return self._celsius

    @celsius.setter
    def celsius(self, valeur):
        if valeur < -273.15:
            raise ValueError("Sous le zéro absolu, impossible")
        self._celsius = valeur

t = Temperature(25)
print(t.celsius)            # 25 (appelle le getter)
t.celsius = 30              # appelle le setter, OK
t.celsius = -300            # ValueError !
TIPEl superpoder — Mantienes la sintaxis t.celsius (simple) pero añades control invisible. El código del usuario no tiene que cambiar nada.

Property de solo lectura

Para un atributo calculado (derivado de otros) que no debe poder modificarse directamente.

output
class Cercle:
    def __init__(self, rayon):
        self.rayon = rayon

    @property
    def diametre(self):
        return self.rayon * 2

    @property
    def aire(self):
        from math import pi
        return pi * self.rayon ** 2

c = Cercle(5)
print(c.diametre)         # 10
print(c.aire)             # 78.539...
# c.aire = 100            # AttributeError : pas de setter

Property completa con getter, setter, deleter

output
class Personne:
    def __init__(self, nom):
        self._nom = nom

    @property
    def nom(self):
        return self._nom

    @nom.setter
    def nom(self, valeur):
        if not isinstance(valeur, str) or len(valeur) < 2:
            raise ValueError("Nom invalide")
        self._nom = valeur.title()      # normalisation

    @nom.deleter
    def nom(self):
        print("Suppression du nom")
        self._nom = None

p = Personne("alice")
print(p.nom)              # Alice (normalisé)
p.nom = "bob"
print(p.nom)              # Bob
del p.nom                 # Suppression du nom

Caso práctico: CompteBancaire con validación

output
class CompteBancaire:
    def __init__(self, titulaire, solde=0):
        self.titulaire = titulaire
        self._solde = 0
        self.solde = solde         # passe par le setter !

    @property
    def solde(self):
        return self._solde

    @solde.setter
    def solde(self, valeur):
        if valeur < 0:
            raise ValueError("Solde négatif interdit")
        self._solde = valeur

    def deposer(self, montant):
        if montant <= 0:
            raise ValueError("Montant doit être positif")
        self.solde += montant       # passe par le setter

    def retirer(self, montant):
        if montant > self._solde:
            raise ValueError("Solde insuffisant")
        self.solde -= montant

c = CompteBancaire("Alice", 1000)
c.deposer(500)
print(c.solde)            # 1500
# c.solde = -100          # ValueError

Herencia simple

NOTEObjetivo — Aprender a crear una nueva clase partiendo de una existente, reutilizando su código y adaptándolo. Es el mecanismo clave para evitar la duplicación de código en POO.

Objetivos pedagógicos

TIPAl finalizar este módulo — Sabrás definir una clase hija que hereda de una clase madre, sobrescribir sus métodos y llamar a la versión padre con super().

El concepto

La herencia permite crear una clase especializada a partir de una clase general. La clase hija recupera todo lo que la clase madre ofrece y luego añade o modifica.

NOTEAnalogía — Un Perro es un Animal. Todo perro tiene comportamientos de animal (comer, dormir), más comportamientos específicos (ladrar). Se dice que Chien es-un Animal.

Primer ejemplo

output
class Animal:
    def __init__(self, nom, age):
        self.nom = nom
        self.age = age

    def manger(self):
        print(f"{self.nom} mange")

    def dormir(self):
        print(f"{self.nom} dort")


class Chien(Animal):
    def aboyer(self):
        print(f"{self.nom} : Wouaf !")


rex = Chien("Rex", 5)
rex.manger()              # hérité d’Animal
rex.dormir()              # hérité d’Animal
rex.aboyer()              # propre à Chien
print(rex.age)            # hérité

Chien no define __init__: Python utiliza automáticamente el de Animal.

Sobrescribir (override) un método

La clase hija puede redefinir un método de la madre para adaptar su comportamiento.

output
class Animal:
    def parler(self):
        print("Bruit générique d’animal")


class Chien(Animal):
    def parler(self):
        print("Wouaf !")


class Chat(Animal):
    def parler(self):
        print("Miaou")


for a in [Chien(), Chat(), Animal()]:
    a.parler()
# Wouaf !
# Miaou
# Bruit générique d’animal
TIPPolimorfismo — La misma llamada a.parler() produce un resultado diferente según la clase real de a. Es uno de los 4 pilares de la POO.

super(): llamar al método padre

Cuando se sobrescribe un método, a menudo se quiere completar el comportamiento padre en lugar de reemplazarlo.

output
class Animal:
    def __init__(self, nom, age):
        self.nom = nom
        self.age = age

    def description(self):
        return f"{self.nom}, {self.age} ans"


class Chien(Animal):
    def __init__(self, nom, age, race):
        super().__init__(nom, age)        # appelle Animal.__init__
        self.race = race

    def description(self):
        base = super().description()       # appelle Animal.description
        return f"{base}, race {self.race}"


rex = Chien("Rex", 5, "Labrador")
print(rex.description())     # Rex, 5 ans, race Labrador
WARNINGRegla — En cuanto una clase hija tiene su propio __init__, debes llamar a super().__init__(...) para inicializar los atributos de la madre. Olvidarlo = bugs garantizados.

Verificar la parentesco: isinstance y issubclass

output
rex = Chien("Rex", 5, "Labrador")

print(isinstance(rex, Chien))      # True
print(isinstance(rex, Animal))     # True (héritage)
print(isinstance(rex, Chat))       # False

print(issubclass(Chien, Animal))   # True
print(issubclass(Animal, Chien))   # False
TIPPythonic — Utiliza isinstance(x, Animal) en lugar de type(x) == Animal. La primera forma respeta la herencia.

¿Cuándo usar la herencia?

Relación¿Herencia?
Chien es-un Animal
Roman es-un Livre
Voiture a-un MoteurNo — composición
Bibliothèque contiene LivresNo — composición
NOTERegla de oro — Prefiere la composición a la herencia. Si la relación no es una verdadera especialización, utiliza un atributo en lugar de herencia.

Caso concreto: aplicación biblioteca

output
class Livre:
    def __init__(self, titre, auteur, isbn):
        self.titre = titre
        self.auteur = auteur
        self.isbn = isbn
        self.disponible = True

    def description(self):
        return f"{self.titre} de {self.auteur}"


class Roman(Livre):
    def __init__(self, titre, auteur, isbn, genre):
        super().__init__(titre, auteur, isbn)
        self.genre = genre

    def description(self):
        return f"{super().description()} -- roman {self.genre}"


class LivreNumerique(Livre):
    def __init__(self, titre, auteur, isbn, format_fichier):
        super().__init__(titre, auteur, isbn)
        self.format_fichier = format_fichier

    def telecharger(self):
        print(f"Téléchargement de {self.titre}.{self.format_fichier}")


dune = Roman("Dune", "Herbert", "978...", "science-fiction")
ebook = LivreNumerique("1984", "Orwell", "978...", "epub")

print(dune.description())       # Dune de Herbert -- roman science-fiction
print(ebook.description())       # 1984 de Orwell
ebook.telecharger()              # Téléchargement de 1984.epub

Jerarquías comunes en Python

Lambda, map, filter, reduce

NOTEObjetivo — Descubrir las funciones anónimas (lambda) y las funciones de orden superior (map, filter, reduce), que permiten transformar y filtrar datos de forma muy concisa.

Objetivos pedagógicos

TIPAl finalizar este módulo — Sabrás cuándo usar una lambda y elegir entre map/filter y una comprensión de lista según el contexto.

¿Qué es una lambda?

Una lambda es una función anónima (sin nombre) que cabe en una sola línea. Se utiliza para operaciones cortas pasadas como argumento a otra función.

Sintaxis

output
lambda parametres: expression

Comparación

output
def doubler(x):
    return x * 2

doubler_lambda = lambda x: x * 2

print(doubler(5))         # 10
print(doubler_lambda(5))  # 10
NOTEAnalogía — Un def clásico es como crear una receta con nombre en un libro. Una lambda es garabatear una receta en un post-it que entregas inmediatamente a alguien.

Lambdas con varios parámetros

output
somme = lambda a, b: a + b
print(somme(3, 4))                       # 7

est_pair = lambda n: n % 2 == 0
print(est_pair(8))                       # True
WARNINGLímite — Una lambda solo contiene una única expresión. Sin return explícito, sin varias líneas. En cuanto sea más complejo, usa def.

map(): transformar cada elemento

map(fonction, iterable) aplica la función a cada elemento y devuelve un iterador. Suele envolverse en list().

output
prix = [10, 25, 7, 50]
prix_ttc = list(map(lambda p: p * 1.20, prix))
print(prix_ttc)        # [12.0, 30.0, 8.4, 60.0]

mots = ["python", "poo", "code"]
majuscules = list(map(str.upper, mots))
print(majuscules)      # ['PYTHON', 'POO', 'CODE']

Con varias secuencias

output
a = [1, 2, 3]
b = [10, 20, 30]
sommes = list(map(lambda x, y: x + y, a, b))
print(sommes)          # [11, 22, 33]

filter(): conservar lo que pasa la prueba

output
notes = [12, 8, 15, 6, 18, 11]
reussies = list(filter(lambda n: n >= 10, notes))
print(reussies)        # [12, 15, 18, 11]

mots = ["chat", "chien", "ours", "lion"]
courts = list(filter(lambda m: len(m) <= 4, mots))
print(courts)          # ['chat', 'ours', 'lion']
va-plus-loin

Este artículo cubre los extractos más útiles: el curso completo Python Intermedio POO (11 capítulos, 36 lecciones, ejercicios corregidos y proyecto final) te lleva hasta el final.

./acceder-au-cours-complet curso gratuito: Dominar Claude Code

FAQ

¿Cuánto tiempo se necesita para aprender Python Intermedio POO?
Con una progresión estructurada (11 capítulos, 36 lecciones cortas y prácticas), se alcanza un nivel operativo en unas semanas dedicando entre 30 y 60 minutos al día. Lo importante es practicar cada concepto de inmediato.
¿Se necesitan requisitos previos?
Basta con nociones básicas de informática. Si sabes usar un terminal y leer código sencillo, estás listo.
¿Por dónde empezar concretamente?
Reproduce los comandos de este artículo y sigue el curso completo Python Intermedio POO: encadena las 36 lecciones en orden, con ejercicios y proyecto final.

📬 ¿Quieres recibir este tipo de guía cada semana? Suscríbete gratis — código real, cero palabrería.