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.
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.
- Introducción e Instalación
- Repaso de Python
- Funciones avanzadas y lambdas
- Clases y objetos
- Herencia y polimorfismo
Encapsulación, properties y setters
Objetivos pedagógicos
_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.
Convenciones de Python
Python no fuerza la confidencialidad (a diferencia de Java). Utiliza convenciones basadas en el nombre.
| Convención | Significado | Efecto real |
|---|---|---|
nom | Público | Acceso libre, forma parte de la API |
_nom | Protegido (convención) | «No tocar, salvo que sepas lo que haces» |
__nom | Privado (name mangling) | Renombrado a _NomClasse__nom |
nom_ | Evita colisión con palabra clave | Ej.: class_ en lugar de class |
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é__ 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
class Temperature:
def __init__(self, celsius):
self.celsius = celsius
t = Temperature(25)
t.celsius = -500 # absurde !
print(t.celsius) # -500No 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.
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 !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.
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 setterProperty completa con getter, setter, deleter
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 nomCaso práctico: CompteBancaire con validación
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 # ValueErrorHerencia simple
Objetivos pedagógicos
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.
Chien es-un Animal.Primer ejemplo
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.
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’animala.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.
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__init__, debes llamar a super().__init__(...) para inicializar los atributos de la madre. Olvidarlo = bugs garantizados.Verificar la parentesco: isinstance y issubclass
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)) # Falseisinstance(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 | Sí |
| Roman es-un Livre | Sí |
| Voiture a-un Moteur | No — composición |
| Bibliothèque contiene Livres | No — composición |
Caso concreto: aplicación biblioteca
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.epubJerarquías comunes en Python
Lambda, map, filter, reduce
lambda) y las funciones de orden superior (map, filter, reduce), que permiten transformar y filtrar datos de forma muy concisa.Objetivos pedagógicos
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
lambda parametres: expression
Comparación
def doubler(x):
return x * 2
doubler_lambda = lambda x: x * 2
print(doubler(5)) # 10
print(doubler_lambda(5)) # 10def 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
somme = lambda a, b: a + b print(somme(3, 4)) # 7 est_pair = lambda n: n % 2 == 0 print(est_pair(8)) # True
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().
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
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
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']
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 CodeFAQ
¿Cuánto tiempo se necesita para aprender Python Intermedio POO?
¿Se necesitan requisitos previos?
¿Por dónde empezar concretamente?
📬 ¿Quieres recibir este tipo de guía cada semana? Suscríbete gratis — código real, cero palabrería.