Comprende la estructura y el propósito de clases y objetos en Programación Orientada a Objetos
La Programación Orientada a Objetos (POO) es un paradigma de programación que organiza el código en objetos que contienen datos y código. En Python, todo es un objeto, lo que hace que POO sea fundamental para el desarrollo efectivo.
Piensa en una clase como un "molde" y en un objeto como la "pieza" creada con ese molde. Por ejemplo, si tienes un molde para hacer galletas (clase), puedes crear muchas galletas (objetos) con diferentes ingredientes pero la misma forma.
Los objetos en Python tienen dos tipos principales de componentes:
Los atributos son las características o datos que almacena el objeto:
# Ejemplo: Clase Persona
class Persona:
def __init__(self, nombre, edad):
self.nombre = nombre # Atributo
self.edad = edad # Atributo
self.ciudad = "Madrid" # Atributo con valor por defecto
# Crear objetos (instancias)
persona1 = Persona("Ana", 25)
persona2 = Persona("Carlos", 30)
print(persona1.nombre) # Ana
print(persona2.edad) # 30
Los métodos son las acciones que puede realizar el objeto:
class Persona:
def __init__(self, nombre, edad):
self.nombre = nombre
self.edad = edad
def saludar(self): # Método
return f"¡Hola! Soy {self.nombre}"
def cumplir_anios(self): # Método
self.edad += 1
return f"¡Feliz cumpleaños! Ahora tengo {self.edad} años"
# Usar métodos
persona = Persona("María", 28)
print(persona.saludar()) # ¡Hola! Soy María
print(persona.cumplir_anios()) # ¡Feliz cumpleaños! Ahora tengo 29 años
Una de las ventajas de POO es que puedes crear múltiples objetos a partir de una sola clase, cada uno con sus propios valores:
class Coche:
def __init__(self, marca, modelo, color):
self.marca = marca
self.modelo = modelo
self.color = color
self.velocidad = 0
def acelerar(self):
self.velocidad += 10
return f"Velocidad actual: {self.velocidad} km/h"
def frenar(self):
self.velocidad = max(0, self.velocidad - 10)
return f"Velocidad actual: {self.velocidad} km/h"
# Crear múltiples instancias
coche1 = Coche("Toyota", "Corolla", "Rojo")
coche2 = Coche("Honda", "Civic", "Azul")
coche3 = Coche("Ford", "Focus", "Verde")
# Cada objeto tiene su propio estado
print(coche1.marca) # Toyota
print(coche2.color) # Azul
print(coche3.modelo) # Focus
# Los métodos afectan solo al objeto específico
coche1.acelerar() # Solo coche1 aumenta velocidad
coche2.acelerar() # Solo coche2 aumenta velocidad
Cada objeto ocupa su propio espacio en memoria y puede ser manipulado independientemente:
# Demostración de objetos independientes
class Contador:
def __init__(self):
self.valor = 0
def incrementar(self):
self.valor += 1
return self.valor
# Crear dos contadores
contador1 = Contador()
contador2 = Contador()
print(contador1.incrementar()) # 1
print(contador1.incrementar()) # 2
print(contador2.incrementar()) # 1 (independiente de contador1)
print(contador1.valor) # 2
print(contador2.valor) # 1
Las herramientas de IA pueden ayudarte a generar clases de manera automatizada y detectar errores de encapsulamiento:
# Prompt para generar una clase de Estudiante
"""
Genera una clase Estudiante en Python con:
- Atributos: nombre, edad, carrera, promedio
- Métodos: estudiar(), tomar_examen(), calcular_promedio()
- Incluye validaciones y documentación
"""
# La IA podría generar algo como:
class Estudiante:
def __init__(self, nombre, edad, carrera):
self.nombre = nombre
self.edad = edad
self.carrera = carrera
self.promedio = 0.0
self.examenes = []
def estudiar(self, horas):
return f"{self.nombre} estudió {horas} horas"
def tomar_examen(self, nota):
self.examenes.append(nota)
self.calcular_promedio()
return f"Examen completado con nota: {nota}"
def calcular_promedio(self):
if self.examenes:
self.promedio = sum(self.examenes) / len(self.examenes)
return self.promedio
Python tiene una sintaxis clara y simple para definir clases:
class NombreClase:
"""Docstring de la clase - documentación"""
# Atributos de clase (compartidos por todas las instancias)
atributo_clase = "valor"
def __init__(self, parametro1, parametro2):
"""Constructor - se ejecuta al crear un objeto"""
self.atributo1 = parametro1 # Atributo de instancia
self.atributo2 = parametro2 # Atributo de instancia
def metodo1(self):
"""Método de instancia"""
return f"Valor: {self.atributo1}"
@classmethod
def metodo_clase(cls):
"""Método de clase"""
return cls.atributo_clase
@staticmethod
def metodo_estatico():
"""Método estático - no necesita self ni cls"""
return "Método estático"
# Ejemplo de convenciones
class MiClase: # PascalCase
ATRIBUTO_CONSTANTE = 100 # MAYÚSCULAS
def __init__(self):
self.atributo_publico = "público" # snake_case
self._atributo_privado = "privado" # _guion_bajo
self.__muy_privado = "muy privado" # __doble_guion
def mi_metodo(self): # snake_case
return self.atributo_publico