Introducción a clases en Python 3 — POO desde cero

Ejemplo completo de programación orientada a objetos en Python 3. Cubre los tres pilares fundamentales: encapsulamiento (atributos protegidos y properties), herencia (Libro y Revista que extienden una clase base) y polimorfismo (una función que trabaja con cualquier subtipo). El código construye un pequeño sistema de biblioteca que sirve de hilo conductor para explicar cada concepto en un contexto real.
				"""
Introducción a clases en Python 3 — Programación orientada a objetos

Una clase es una plantilla que define atributos (datos) y métodos (funciones).
Los objetos son instancias de esa plantilla: cada objeto tiene sus propios
valores para los atributos, pero comparte la estructura definida en la clase.

Este ejemplo construye un sistema de biblioteca sencillo que muestra los
conceptos fundamentales: encapsulamiento, herencia y polimorfismo.

Código mejorado por David Carrero — https://carrero.es
Fecha de modificación: 2026-05-09
"""


# ?? 1. Clase base ?????????????????????????????????????????????????????????????

class ElementoBiblioteca:
"""Clase base para cualquier elemento de una biblioteca."""

def __init__(self, titulo: str, año: int):
self.titulo = titulo
self.año = año
self._prestado = False # atributo protegido (convención: _)

def prestar(self) -> bool:
if self._prestado:
print(f'"{self.titulo}" ya está prestado.')
return False
self._prestado = True
print(f'"{self.titulo}" prestado correctamente.')
return True

def devolver(self) -> None:
self._prestado = False
print(f'"{self.titulo}" devuelto. Gracias.')

@property
def disponible(self) -> bool:
"""Property: acceso de solo lectura al estado interno."""
return not self._prestado

def __str__(self) -> str:
estado = 'disponible' if self.disponible else 'prestado'
return f'[{estado}] {self.titulo} ({self.año})'


# ?? 2. Herencia ???????????????????????????????????????????????????????????????

class Libro(ElementoBiblioteca):
"""Un libro hereda de ElementoBiblioteca y añade atributos propios."""

def __init__(self, titulo: str, autor: str, año: int, paginas: int):
super().__init__(titulo, año) # llama al __init__ del padre
self.autor = autor
self.paginas = paginas

def __str__(self) -> str:
base = super().__str__()
return f'{base} — {self.autor}, {self.paginas} págs.'


class Revista(ElementoBiblioteca):
"""Una revista también hereda de ElementoBiblioteca."""

def __init__(self, titulo: str, numero: int, año: int):
super().__init__(titulo, año)
self.numero = numero

def __str__(self) -> str:
base = super().__str__()
return f'{base} — nº {self.numero}'


# ?? 3. Polimorfismo ???????????????????????????????????????????????????????????

def mostrar_catalogo(elementos: list[ElementoBiblioteca]) -> None:
"""
Recibe una lista de ElementoBiblioteca (pueden ser Libros o Revistas)
y los muestra todos. Esto es polimorfismo: __str__ se comporta distinto
según la clase real de cada objeto.
"""
print('n?? Catálogo ????????????????????????????????')
for elem in elementos:
print(' •', elem) # llama a __str__ de cada subclase
print(f'Total: {len(elementos)} elementos')


# ?? 4. Programa de demostración ???????????????????????????????????????????????

if __name__ == '__main__':
# Crear instancias
libro1 = Libro('El Quijote', 'Cervantes', 1605, 863)
libro2 = Libro('Clean Code', 'Robert C. Martin', 2008, 464)
libro3 = Libro('Python Crash Course', 'Eric Matthes', 2019, 544)
revista1 = Revista('National Geographic', 382, 2024)
revista2 = Revista('Linux Magazine', 276, 2024)

catalogo: list[ElementoBiblioteca] = [libro1, libro2, libro3, revista1, revista2]

# Ver catálogo inicial
mostrar_catalogo(catalogo)

# Préstamos
print('n?? Operaciones de préstamo ?????????????????')
libro1.prestar()
libro1.prestar() # intentar prestar dos veces
revista1.prestar()

# Ver estado actualizado
mostrar_catalogo(catalogo)

# Devoluciones
print('n?? Devoluciones ????????????????????????????')
libro1.devolver()
mostrar_catalogo(catalogo)
Descargar adjuntos
COMPARTE ESTE TUTORIAL

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP