0% encontró este documento útil (0 votos)
4 vistas

python 3

El documento explica el concepto de clases y objetos en Python, destacando la importancia de la programación orientada a objetos. Se describen las características de las clases, la inicialización de objetos mediante el método __init__, y se presentan ejemplos de herencia y encapsulamiento. Además, se abordan métodos especiales que permiten personalizar el comportamiento de las clases.

Cargado por

dantberned
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
4 vistas

python 3

El documento explica el concepto de clases y objetos en Python, destacando la importancia de la programación orientada a objetos. Se describen las características de las clases, la inicialización de objetos mediante el método __init__, y se presentan ejemplos de herencia y encapsulamiento. Además, se abordan métodos especiales que permiten personalizar el comportamiento de las clases.

Cargado por

dantberned
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 37

Clases y Objetos en Python

Python es un lenguaje orientado a objetos (OOP - Object-Oriented Programming). Esto


significa que permite estructurar el código en clases y objetos, lo que facilita la
reutilización y organización del código.

1 ¿Qué es una Clase?


Una clase es una plantilla para crear objetos. Define atributos (datos) y métodos
(funciones que operan sobre esos datos).

Ejemplo de Clase en Python


class Persona:
def __init__(self, nombre, edad):
self.nombre = nombre # Atributo de instancia
self.edad = edad # Atributo de instancia

def saludar(self):
return f"Hola, mi nombre es {self.nombre} y tengo {self.edad}
años."

📌 Características de una clase:

 Se define con class NombreClase.


 Tiene un método especial __init__, que se ejecuta al crear un objeto.
 Los atributos (self.nombre, self.edad) almacenan datos.
 Los métodos (saludar()) permiten realizar acciones.

Observacion

__init__ es un método especial en Python que se usa como el constructor de una clase.
Se ejecuta automáticamente cuando se crea una nueva instancia de la clase y se utiliza para
inicializar atributos.

🔹 Ejemplo básico de __init__


class Perro: # Definir la clase
def __init__(self, nombre, raza): # Constructor
self.nombre = nombre
self.raza = raza

def __init__(self, nombre, raza):


self.nombre = nombre # Se guarda el nombre en el objeto
self.raza = raza # Se guarda la raza en el objeto

def ladrar(self):
print(f"{self.nombre} está ladrando 🐶")
# Crear un objeto (instancia) de la clase Perro
mi_perro = Perro("Firulais", "Labrador")

print(mi_perro.nombre) # Firulais
print(mi_perro.raza) # Labrador
mi_perro.ladrar() # Firulais está ladrando 🐶🔹 Explicación

1. __init__ se llama automáticamente cuando creamos un objeto de la clase.


2. Recibe parámetros (en este caso, nombre y raza).
3. Usa self para asignar esos valores como atributos del objeto.
4. Ahora, cada objeto creado con Perro() tendrá su propio nombre y raza.

🔹 Sin __init__

Si no usas __init__, tendrías que asignar los atributos manualmente:

class Perro:
pass

mi_perro = Perro()
mi_perro.nombre = "Firulais"
mi_perro.raza = "Labrador"
print(mi_perro.nombre) # Firulais

Esto funciona, pero __init__ hace que el código sea más organizado y fácil de manejar.

🔹 Ejemplo en el contexto de Binance

En la librería de Binance, cuando usas:

client = Client('api_key', 'api_secret')

El __init__ de Client está inicializando la conexión con la API de Binance, configurando


las claves y preparando todo para que puedas hacer consultas sin preocuparte por los
detalles internos.

Observacion: debes definir la clase Perro antes de crear un objeto de ella, asegúrate de que
ladrar esté dentro de la clase Perro, con la indentación correcta:

class Perro: # Definir la clase


def __init__(self, nombre, raza): # Constructor
self.nombre = nombre
self.raza = raza
🔹 Conclusión

✅ __init__ se usa para inicializar objetos cuando creamos una nueva instancia de una
clase.
✅ Es útil para asignar valores a atributos y evitar configuraciones manuales.

2️¿Qué es un Objeto?
Un objeto es una instancia de una clase, es decir, una entidad creada a partir de una
plantilla (clase).

Ejemplo de Creación de Objetos


persona1 = Persona("Carlos", 30) # Crear un objeto de la clase Persona
persona2 = Persona("Ana", 25)

print(persona1.saludar()) # "Hola, mi nombre es Carlos y tengo 30 años."


print(persona2.saludar()) # "Hola, mi nombre es Ana y tengo 25 años."

📌 Explicación:

 persona1 y persona2 son objetos de la clase Persona.


 Se asignan valores a nombre y edad al crearlos.
 Se usa saludar() para mostrar información del objeto.

3️Métodos de Clase y Métodos de Instancia


Python permite definir diferentes tipos de métodos dentro de una clase.

Métodos de Instancia (self)

Son los métodos más comunes, operan sobre datos del objeto y usan self.

class Persona:
def __init__(self, nombre, edad):
self.nombre = nombre
self.edad = edad

def cumplir_años(self):
self.edad += 1 # Modifica la edad del objeto

persona = Persona("Luis", 28)


persona.cumplir_años()
print(persona.edad) # 29
Métodos de Clase (@classmethod)

📌 Usan @classmethod y operan sobre la clase en sí, no sobre un objeto individual.

class Persona:
contador = 0 # Atributo de clase

def __init__(self, nombre):


self.nombre = nombre
Persona.contador += 1 # Aumenta cada vez que se crea un objeto

@classmethod
def cantidad_personas(cls):
return f"Se han creado {cls.contador} personas."

p1 = Persona("Carlos")
p2 = Persona("Ana")

print(Persona.cantidad_personas()) # "Se han creado 2 personas."

Métodos Estáticos (@staticmethod)

📌 No acceden ni a self (instancia) ni a cls (clase). Son métodos independientes.

python
CopiarEditar
class Utilidades:
@staticmethod
def es_mayor_de_edad(edad):
return edad >= 18

print(Utilidades.es_mayor_de_edad(20)) # True
print(Utilidades.es_mayor_de_edad(15)) # False

💡 Se usa cuando una función no depende de la instancia ni de la clase.

4️Herencia (Reutilización de Código)


📌 La herencia permite crear una nueva clase basada en otra ya existente.

Ejemplo de Herencia
class Persona:
def __init__(self, nombre, edad):
self.nombre = nombre
self.edad = edad

def presentarse(self):
return f"Soy {self.nombre} y tengo {self.edad} años."

class Estudiante(Persona): # Hereda de Persona


def __init__(self, nombre, edad, carrera):
super().__init__(nombre, edad) # Llamar al constructor de
Persona
self.carrera = carrera

def presentarse(self):
return f"Soy {self.nombre}, tengo {self.edad} años y estudio
{self.carrera}."

estudiante = Estudiante("María", 22, "Ingeniería")


print(estudiante.presentarse())
# "Soy María, tengo 22 años y estudio Ingeniería."

📌 Características de la herencia:

 Estudiante(Persona): La clase Estudiante hereda de Persona.


 super().__init__(...): Llama al constructor de Persona para inicializar nombre
y edad.
 presentarse(): Se sobreescribe el método para personalizarlo.

5️Encapsulamiento (Atributos Privados)


📌 Python permite definir atributos públicos, protegidos y privados.

Ejemplo de Atributos Privados


class CuentaBancaria:
def __init__(self, saldo):
self.__saldo = saldo # Atributo privado

def depositar(self, cantidad):


self.__saldo += cantidad

def obtener_saldo(self):
return self.__saldo

cuenta = CuentaBancaria(1000)
cuenta.depositar(500)
print(cuenta.obtener_saldo()) # 1500

# print(cuenta.__saldo) # ❌ Esto generará un error (atributo privado)

📌 Notas:

 __saldo: Doble guion bajo lo hace privado (no accesible desde fuera).
 Se accede a él usando métodos (obtener_saldo()).
6️Ejemplo Propuesto: Sistema de Vehículos
📌 Objetivo: Crear una clase Vehiculo y dos clases Coche y Moto que hereden
de ella.

✅ Código
python
CopiarEditar
class Vehiculo:
def __init__(self, marca, modelo):
self.marca = marca
self.modelo = modelo

def descripcion(self):
return f"Vehículo {self.marca} modelo {self.modelo}."

class Coche(Vehiculo):
def __init__(self, marca, modelo, puertas):
super().__init__(marca, modelo)
self.puertas = puertas

def descripcion(self):
return f"Coche {self.marca} modelo {self.modelo} con
{self.puertas} puertas."

class Moto(Vehiculo):
def __init__(self, marca, modelo, cilindrada):
super().__init__(marca, modelo)
self.cilindrada = cilindrada

def descripcion(self):
return f"Moto {self.marca} modelo {self.modelo} de
{self.cilindrada}cc."

coche = Coche("Toyota", "Corolla", 4)


moto = Moto("Yamaha", "R1", 1000)

print(coche.descripcion()) # Coche Toyota modelo Corolla con 4 puertas.


print(moto.descripcion()) # Moto Yamaha modelo R1 de 1000cc.

📌 Resumen
Concepto Descripción
Clase Plantilla para crear objetos.
Objeto Instancia de una clase.
Métodos Funciones dentro de una clase.
Concepto Descripción
Herencia Crear una nueva clase basada en otra.
Encapsulamiento Controlar el acceso a los datos.

🚀 ¿Quieres que profundicemo


Métodos Especiales en Python (__metodo__)
Los métodos especiales son funciones que Python llama automáticamente en ciertas
situaciones. Se escriben con doble guion bajo (__nombre__) y permiten personalizar el
comportamiento de una clase.

1 __init__ (Constructor de la clase)


1️⃣
📌 Se ejecuta automáticamente cuando se crea un objeto. Se usa para inicializar atributos.

python
CopiarEditar
class Persona:
def __init__(self, nombre, edad):
self.nombre = nombre
self.edad = edad

persona = Persona("Carlos", 30)


print(persona.nombre) # "Carlos"
print(persona.edad) # 30

🔹 Ejemplo propuesto: Crea una clase Coche que tenga atributos marca, modelo y año.

2️⃣__str__ (Representación en texto)


📌 Define lo que se muestra cuando usas print(objeto).

python
CopiarEditar
class Persona:
def __init__(self, nombre, edad):
self.nombre = nombre
self.edad = edad

def __str__(self):
return f"Persona(nombre={self.nombre}, edad={self.edad})"

persona = Persona("Ana", 25)


print(persona) # "Persona(nombre=Ana, edad=25)"

🔹 Ejemplo propuesto: Modifica la clase Coche para que print(coche) muestre "Coche
Toyota Corolla 2022".
3️⃣__repr__ (Representación oficial del objeto)
📌 Es similar a __str__, pero su propósito es ser más técnico (para depuración).

python
CopiarEditar
class Persona:
def __init__(self, nombre, edad):
self.nombre = nombre
self.edad = edad

def __repr__(self):
return f"Persona('{self.nombre}', {self.edad})"

persona = Persona("Luis", 28)


print(repr(persona)) # "Persona('Luis', 28)"

🔹 Diferencia entre __str__ y __repr__:

 __str__: Para usuarios finales (más legible).


 __repr__: Para desarrolladores (más detallado).

4️⃣__len__ (Longitud del objeto)


📌 Define lo que devuelve len(objeto).

python
CopiarEditar
class Grupo:
def __init__(self, miembros):
self.miembros = miembros

def __len__(self):
return len(self.miembros)

grupo = Grupo(["Ana", "Luis", "Carlos"])


print(len(grupo)) # 3

🔹 Ejemplo propuesto: Crea una clase Biblioteca que tenga una lista de libros y usa
__len__ para devolver cuántos libros hay.

5️⃣__call__ (Hacer el objeto invocable)


📌 Permite llamar un objeto como si fuera una función.

python
CopiarEditar
class Saludo:
def __call__(self, nombre):
return f"¡Hola, {nombre}!"

saludar = Saludo()
print(saludar("Juan")) # "¡Hola, Juan!"

🔹 Ejemplo propuesto: Crea una clase Multiplicador que, al llamarla, multiplique un


número por un valor fijo.

6️⃣__getitem__, __setitem__, __delitem__ (Manipular índices como


listas)
📌 Permiten acceder, modificar y eliminar elementos con objeto[indice].

python
CopiarEditar
class ListaPersonalizada:
def __init__(self, datos):
self.datos = datos

def __getitem__(self, indice):


return self.datos[indice]

def __setitem__(self, indice, valor):


self.datos[indice] = valor

def __delitem__(self, indice):


del self.datos[indice]

lista = ListaPersonalizada([10, 20, 30])


print(lista[1]) # 20
lista[1] = 99
print(lista[1]) # 99
del lista[1]
print(lista.datos) # [10, 30]

🔹 Ejemplo propuesto: Crea una clase Agenda que almacene contactos y permita acceder a
ellos con agenda[nombre].

7️⃣__contains__ (Operador in)


📌 Permite definir el comportamiento del operador in.

python
CopiarEditar
class Grupo:
def __init__(self, miembros):
self.miembros = miembros

def __contains__(self, persona):


return persona in self.miembros

grupo = Grupo(["Ana", "Luis", "Carlos"])


print("Ana" in grupo) # True
print("Pedro" in grupo) # False

🔹 Ejemplo propuesto: Crea una clase Inventario donde puedas verificar si un producto
está disponible con if "manzana" in inventario:.

8️⃣__eq__, __lt__, __gt__ (Comparación de Objetos)


📌 Permiten definir cómo se comparan los objetos con ==, <, >.

python
CopiarEditar
class Persona:
def __init__(self, nombre, edad):
self.nombre = nombre
self.edad = edad

def __eq__(self, otro):


return self.edad == otro.edad

def __lt__(self, otro):


return self.edad < otro.edad

p1 = Persona("Carlos", 30)
p2 = Persona("Ana", 25)

print(p1 == p2) # False


print(p1 < p2) # False (porque 30 no es menor que 25)

🔹 Ejemplo propuesto: Crea una clase Producto que compare dos productos por su precio.

9️⃣__add__, __sub__, __mul__ (Operaciones Aritméticas)


📌 Personalizan operadores matemáticos como +, -, *.
python
CopiarEditar
class Numero:
def __init__(self, valor):
self.valor = valor

def __add__(self, otro):


return Numero(self.valor + otro.valor)

def __str__(self):
return str(self.valor)

n1 = Numero(10)
n2 = Numero(5)

n3 = n1 + n2
print(n3) # 15

🔹 Ejemplo propuesto: Crea una clase Tiempo que permita sumar horas y minutos con +.

🔹 Resumen de Métodos Especiales


Método Propósito
__init__ Constructor de la clase.
__str__ Representación en texto (print).
__repr__ Representación técnica (depuración).
__len__ Longitud del objeto (len(objeto)).
__call__ Hacer el objeto invocable como función.
__getitem__ Permitir acceso con índices (objeto[indice]).
__setitem__ Modificar valores con índices (objeto[indice] = valor).
__delitem__ Eliminar valores con índices (del objeto[indice]).
__contains__ Controlar el operador in.
__eq__, __lt__, __gt__ Comparar objetos con ==, <, >.
__add__, __sub__, __mul__ Permitir operaciones matemáticas.

Comunicación entre Objetos en Python


En programación orientada a objetos (POO), la comunicación entre objetos es el proceso
en el que un objeto interactúa con otro para intercambiar datos o ejecutar métodos.
Esto es esencial para crear sistemas más modulares y organizados.
📌 Formas de comunicación entre objetos:1️⃣11 Composición (Un objeto contiene a otro)
2️⃣Asociación (Un objeto usa a otro, pero no lo contiene)
3️⃣Herencia (Un objeto es una especialización de otro)

1️⃣Comunicación por Composición


📌 Un objeto contiene a otro dentro de él (relación "tiene un").
📌 Se usa cuando un objeto forma parte de otro.

Ejemplo: Un Coche tiene un Motor


python
CopiarEditar
class Motor:
def __init__(self, potencia):
self.potencia = potencia

def arrancar(self):
return "Motor encendido"

class Coche:
def __init__(self, marca, motor_potencia):
self.marca = marca
self.motor = Motor(motor_potencia) # Un objeto dentro de otro

def encender(self):
return f"{self.marca}: {self.motor.arrancar()}"

mi_coche = Coche("Toyota", 120)


print(mi_coche.encender()) # "Toyota: Motor encendido"

✅ Observaciones:

 Coche contiene un objeto Motor.


 Coche usa el método arrancar() de Motor.

🔹 Ejemplo propuesto:
Crea una clase Casa que tenga objetos Habitacion. Cada Habitacion tiene un nombre y
un tamaño.

2️⃣Comunicación por Asociación


📌 Un objeto usa a otro, pero no lo contiene (relación "usa un").
📌 Se usa cuando un objeto necesita interactuar con otro sin depender de él
permanentemente.

Ejemplo: Un Alumno usa un Libro


python
CopiarEditar
class Libro:
def __init__(self, titulo):
self.titulo = titulo

class Alumno:
def __init__(self, nombre):
self.nombre = nombre

def leer(self, libro):


return f"{self.nombre} está leyendo {libro.titulo}"

mi_libro = Libro("Python para Todos")


alumno = Alumno("Carlos")

print(alumno.leer(mi_libro)) # "Carlos está leyendo Python para Todos"

✅ Observaciones:

 Alumno usa Libro, pero no lo contiene dentro de sí.


 Se establece la relación pasando Libro como argumento.

🔹 Ejemplo propuesto:
Crea una clase Piloto que use un objeto Avion para volar.

3️⃣Comunicación por Herencia


📌 Un objeto hereda características y comportamientos de otro (relación "es un").
📌 Se usa cuando un objeto es una especialización de otro.

Ejemplo: Un Perro es un tipo de Animal


python
CopiarEditar
class Animal:
def __init__(self, nombre):
self.nombre = nombre

def hacer_sonido(self):
return "Sonido genérico"
class Perro(Animal): # Herencia
def hacer_sonido(self):
return "Guau guau"

mi_perro = Perro("Firulais")
print(mi_perro.hacer_sonido()) # "Guau guau"

✅ Observaciones:

 Perro hereda de Animal.


 Perro sobrescribe el método hacer_sonido().

🔹 Ejemplo propuesto:
Crea una clase Gato que herede de Animal y defina su propio sonido.

🔹 Resumen de la Comunicación entre


Objetos
Tipo de Relación Descripción Ejemplo

Composición Un objeto contiene a otro. Coche tiene un Motor.

Asociación Un objeto usa a otro, pero no lo contiene. Alumno usa un Libro.

Herencia Un objeto es una especialización de otro. Perro hereda de Animal.

🚀 ¿Necesitas más ejemplos o una explicación más detallada en algún punto? 😊

4o

Dijiste:
ahora sobre Comunicando a objetos - Juego

ChatGPT dijo:

🔹 Comunicación entre Objetos en un Juego en Python

En los videojuegos, los objetos interactúan constantemente entre sí: un personaje recoge
objetos, ataca enemigos, abre puertas, etc. Para modelar estas interacciones en Python,
usamos composición, asociación y herencia.
1️⃣Comunicación por Composición
📌 Ejemplo: Un Jugador tiene una Espada Un jugador puede tener un arma equipada que
le da un ataque especial.

python
CopiarEditar
class Espada:
def __init__(self, daño):
self.daño = daño

def atacar(self):
return f"Golpe con {self.daño} de daño"

class Jugador:
def __init__(self, nombre, arma):
self.nombre = nombre
self.arma = arma # Contiene un objeto Espada

def atacar(self):
return f"{self.nombre} {self.arma.atacar()}"

espada = Espada(50)
jugador = Jugador("Héroe", espada)

print(jugador.atacar()) # "Héroe Golpe con 50 de daño"

✅ Aquí, el Jugador contiene un Espada, lo que representa la composición.

🔹 Ejemplo propuesto:
Crea una clase Escudo que tenga un atributo defensa y agrégalo a Jugador.

2️⃣Comunicación por Asociación


📌 Ejemplo: Un Jugador lucha contra un Enemigo El jugador y el enemigo se encuentran
en batalla, pero no se contienen mutuamente.

python
CopiarEditar
class Enemigo:
def __init__(self, nombre, vida):
self.nombre = nombre
self.vida = vida

def recibir_ataque(self, daño):


self.vida -= daño
return f"{self.nombre} ahora tiene {self.vida} de vida"

class Jugador:
def __init__(self, nombre, ataque):
self.nombre = nombre
self.ataque = ataque

def atacar(self, enemigo):


return enemigo.recibir_ataque(self.ataque)

jugador = Jugador("Héroe", 30)


enemigo = Enemigo("Orco", 100)

print(jugador.atacar(enemigo)) # "Orco ahora tiene 70 de vida"

✅ Aquí, Jugador interactúa con Enemigo, pero no lo contiene, lo que representa


asociación.

🔹 Ejemplo propuesto:
Crea una clase Hechizo que un Mago pueda lanzar sobre un Enemigo.

3️⃣Comunicación por Herencia


📌 Ejemplo: Guerrero y Mago heredan de Jugador Ambos personajes pueden atacar, pero
de manera diferente.

python
CopiarEditar
class Jugador:
def __init__(self, nombre, ataque):
self.nombre = nombre
self.ataque = ataque

def atacar(self):
return f"{self.nombre} ataca con {self.ataque} de daño"

class Guerrero(Jugador):
def atacar(self):
return f"{self.nombre} ataca con espada e inflige {self.ataque}
de daño"

class Mago(Jugador):
def atacar(self):
return f"{self.nombre} lanza un hechizo y causa {self.ataque} de
daño mágico"

guerrero = Guerrero("Conan", 40)


mago = Mago("Merlín", 50)

print(guerrero.atacar()) # "Conan ataca con espada e inflige 40 de daño"


print(mago.atacar()) # "Merlín lanza un hechizo y causa 50 de daño
mágico"
✅ Aquí, Guerrero y Mago heredan de Jugador, lo que representa herencia.

🔹 Ejemplo propuesto:
Añade una clase Arquero que herede de Jugador y use flechas.

🔹 Resumen de Comunicación entre


Objetos en un Juego
Tipo de Relación Descripción Ejemplo en Juego

Composición Un objeto contiene a otro. Jugador tiene una Espada.

Un objeto usa a otro, pero no lo


Asociación Jugador ataca a Enemigo.
contiene.

Un objeto es una especialización de Guerrero y Mago heredan de


Herencia
otro. Jugador.

🚀 ¿Quieres que hagamos un juego más completo con estas ideas? 😃

4o

Dijiste:
ahora sobre herencia

ChatGPT dijo:

🔹 Herencia en Python

La herencia es un pilar fundamental de la Programación Orientada a Objetos (POO) que


permite que una clase nueva adquiera atributos y métodos de otra clase.

✅ Ventajas de la Herencia:
✔️Evita repetir código.
✔️Permite organizar mejor el programa.
✔️Facilita la extensión y el mantenimiento del código.

1️⃣Herencia Básica
📌 Ejemplo: Animal → Perro

python
CopiarEditar
class Animal:
def __init__(self, nombre):
self.nombre = nombre

def hacer_sonido(self):
return "Sonido genérico"

class Perro(Animal): # Herencia de Animal


def hacer_sonido(self):
return "Guau guau"

perro = Perro("Firulais")
print(perro.nombre) # Firulais (heredado de Animal)
print(perro.hacer_sonido()) # Guau guau (sobrescrito en Perro)

✅ Observaciones:

 Perro hereda de Animal, por lo que obtiene su atributo nombre.


 Se sobrescribe (override) el método hacer_sonido().

🔹 Ejemplo propuesto:
Crea una clase Gato que herede de Animal y haga "Miau miau".

2️⃣Uso de super() para Extender Funcionalidad


📌 Ejemplo: Empleado → Gerente

python
CopiarEditar
class Empleado:
def __init__(self, nombre, salario):
self.nombre = nombre
self.salario = salario

def mostrar_info(self):
return f"Empleado: {self.nombre}, Salario: {self.salario}"

class Gerente(Empleado):
def __init__(self, nombre, salario, departamento):
super().__init__(nombre, salario) # Llama al constructor de
Empleado
self.departamento = departamento

def mostrar_info(self):
return f"Gerente: {self.nombre}, Salario: {self.salario},
Departamento: {self.departamento}"
gerente = Gerente("Carlos", 5000, "Ventas")
print(gerente.mostrar_info())
# "Gerente: Carlos, Salario: 5000, Departamento: Ventas"

✅ Observaciones:

 super().__init__() llama al constructor de la clase padre (Empleado).


 Gerente agrega un atributo departamento y sobrescribe mostrar_info().

🔹 Ejemplo propuesto:
Crea una clase Director que herede de Gerente y tenga un atributo empresa.

3️⃣Herencia Múltiple
📌 Ejemplo: Mamífero + Volador → Murciélago

python
CopiarEditar
class Mamifero:
def amamantar(self):
return "Amamantando crías"

class Volador:
def volar(self):
return "Volando alto"

class Murcielago(Mamifero, Volador): # Hereda de dos clases


def hacer_sonido(self):
return "Chirp chirp"

murcielago = Murcielago()
print(murcielago.amamantar()) # "Amamantando crías"
print(murcielago.volar()) # "Volando alto"
print(murcielago.hacer_sonido()) # "Chirp chirp"

✅ Observaciones:

 Murciélago hereda de Mamífero y Volador.


 Puede usar métodos de ambas clases.

🔹 Ejemplo propuesto:
Crea una clase Anfibio que herede de Acuatico y Terrestre.

4️⃣Herencia y isinstance()
📌 Ejemplo: Verificar si un objeto pertenece a una clase

python
CopiarEditar
class Persona:
pass

class Estudiante(Persona):
pass

juan = Estudiante()

print(isinstance(juan, Estudiante)) # True


print(isinstance(juan, Persona)) # True (porque Estudiante hereda de
Persona)
print(isinstance(juan, object)) # True (todas las clases heredan de
object)

✅ Observaciones:

 isinstance(objeto, Clase) verifica si un objeto es instancia de una clase o de sus


padres.

🔹 Ejemplo propuesto:
Crea una clase Profesor y verifica si un objeto pertenece a Profesor o Persona.

🔹 Resumen de Herencia en Python


Concepto Descripción Ejemplo

Una clase hereda atributos/métodos


Herencia Básica Perro hereda de Animal.
de otra.

Uso de super() Llama métodos de la clase padre. Gerente extiende Empleado.

Herencia Murciélago hereda de Mamífero y


Una clase hereda de varias clases.
Múltiple Volador.

isinstance(juan, Persona) →
isinstance() Verifica si un objeto es de una clase.
True.

🚀 ¿Quieres que hagamos algo más avanzado con herencia? 😃

4o
Dijiste:
mas ejemplos y problemas propuestos

ChatGPT dijo:

Aquí tienes más ejemplos y problemas propuestos sobre herencia en Python, organizados
desde lo básico hasta lo avanzado. 🚀

🔹 Ejemplo 1: Vehículos (Herencia Básica)


📌 Escenario:
Queremos modelar diferentes tipos de vehículos que compartan características comunes.

python
CopiarEditar
class Vehiculo:
def __init__(self, marca, modelo):
self.marca = marca
self.modelo = modelo

def describir(self):
return f"Vehículo {self.marca} {self.modelo}"

class Coche(Vehiculo):
def __init__(self, marca, modelo, puertas):
super().__init__(marca, modelo)
self.puertas = puertas

def describir(self):
return f"Coche {self.marca} {self.modelo}, {self.puertas}
puertas"

class Moto(Vehiculo):
def __init__(self, marca, modelo, cilindrada):
super().__init__(marca, modelo)
self.cilindrada = cilindrada

def describir(self):
return f"Moto {self.marca} {self.modelo}, {self.cilindrada} cc"

coche = Coche("Toyota", "Corolla", 4)


moto = Moto("Yamaha", "YZF-R3", 321)

print(coche.describir()) # "Coche Toyota Corolla, 4 puertas"


print(moto.describir()) # "Moto Yamaha YZF-R3, 321 cc"

✅ Conceptos aplicados:

 Herencia básica: Coche y Moto heredan de Vehiculo.


 Uso de super() para reutilizar atributos del padre.
 Sobrescritura de métodos (describir()).

🔹 Problema propuesto:
Crea una clase Camion que herede de Vehiculo y agregue un atributo capacidad_carga.

🔹 Ejemplo 2: Sistema de Empleados


(Herencia y Métodos Sobrescritos)
📌 Escenario:
Tenemos diferentes tipos de empleados con diferentes formas de calcular su salario.

class Empleado:
def __init__(self, nombre, salario_base):
self.nombre = nombre
self.salario_base = salario_base

def calcular_salario(self):
return self.salario_base

class EmpleadoTiempoCompleto(Empleado):
def calcular_salario(self):
return self.salario_base # Mismo salario base

class EmpleadoPorHoras(Empleado):
def __init__(self, nombre, tarifa_hora, horas_trabajadas):
super().__init__(nombre, tarifa_hora * horas_trabajadas)

def calcular_salario(self):
return self.salario_base # Salario basado en horas trabajadas

empleado_fijo = EmpleadoTiempoCompleto("Carlos", 3000)


empleado_horas = EmpleadoPorHoras("Ana", 20, 120) # $20/hora, 120 horas

print(empleado_fijo.calcular_salario()) # 3000
print(empleado_horas.calcular_salario()) # 2400

✅ Conceptos aplicados:

 Herencia básica con EmpleadoTiempoCompleto y EmpleadoPorHoras.


 Sobrescritura de métodos para personalizar cálculos.

🔹 Problema propuesto:
Crea una clase Gerente que tenga un bono adicional en su salario.
🔹 Ejemplo 3: Videojuego con Herencia
Múltiple
📌 Escenario:
En un videojuego, tenemos personajes que pueden ser magos y/o guerreros, cada uno con
habilidades distintas.

class Guerrero:
def atacar(self):
return "Ataca con espada"

class Mago:
def lanzar_hechizo(self):
return "Lanza un hechizo de fuego"

class Paladin(Guerrero, Mago): # Herencia múltiple


def habilidades(self):
return f"{self.atacar()} y {self.lanzar_hechizo()}"

paladin = Paladin()
print(paladin.habilidades()) # "Ataca con espada y Lanza un hechizo de
fuego"

✅ Conceptos aplicados:

 Herencia múltiple: Paladin hereda de Guerrero y Mago.


 Uso de métodos de ambas clases padres.

🔹 Problema propuesto:
Crea una clase Arquero que herede de Guerrero y tenga un método disparar_flecha().

🔹 Ejemplo 4: Herencia y isinstance()


📌 Escenario:
Queremos verificar si un objeto pertenece a una clase específica o a una de sus clases base.

class Persona:
pass

class Estudiante(Persona):
pass

juan = Estudiante()

print(isinstance(juan, Estudiante)) # True


print(isinstance(juan, Persona)) # True (porque Estudiante hereda de
Persona)
print(isinstance(juan, object)) # True (todo en Python hereda de
`object`)

✅ Conceptos aplicados:

 Verificación de tipos con isinstance().


 Todo en Python hereda de object.

🔹 Problema propuesto:
Crea una clase Profesor que herede de Persona y verifica si un objeto de Profesor es
instancia de Persona.

🔹 Ejemplo 5: Uso Avanzado de super()


📌 Escenario:
En un zoológico, queremos representar animales terrestres y acuáticos con características
comunes y específicas.

class Animal:
def __init__(self, nombre):
self.nombre = nombre

def info(self):
return f"Soy un animal llamado {self.nombre}"

class Terrestre(Animal):
def __init__(self, nombre, velocidad):
super().__init__(nombre)
self.velocidad = velocidad

def info(self):
return f"{super().info()} y corro a {self.velocidad} km/h"

class Acuatico(Animal):
def __init__(self, nombre, profundidad):
super().__init__(nombre)
self.profundidad = profundidad

def info(self):
return f"{super().info()} y nado a {self.profundidad} metros de
profundidad"

tigre = Terrestre("Tigre", 60)


delfin = Acuatico("Delfín", 200)

print(tigre.info()) # "Soy un animal llamado Tigre y corro a 60 km/h"


print(delfin.info()) # "Soy un animal llamado Delfín y nado a 200 metros
de profundidad"

✅ Conceptos aplicados:

 Uso de super() para reutilizar código.


 Sobrescritura de métodos.

🔹 Problema propuesto:
Crea una clase Anfibio que herede de Terrestre y Acuatico, combinando ambas
características.

🔹 Resumen de Problemas Propuestos


Número Descripción del Problema

1️⃣ Crea una clase Camion que herede de Vehiculo y tenga capacidad_carga.

2️⃣ Crea una clase Gerente que herede de Empleado y tenga un bono extra.

3️⃣ Crea una clase Arquero que herede de Guerrero y dispare flechas.

4️⃣ Crea una clase Profesor que herede de Persona y verifica su tipo con isinstance().

5️⃣ Crea una clase Anfibio que combine Terrestre y Acuatico.

🚀 ¿Quieres que desarrolle alguno de los problemas propuestos? 😃

4o
Dijiste:
ahora sobre • Decorador @property

ChatGPT dijo:

🔹 Decorador @property en Python

El decorador @property permite definir métodos que pueden ser accedidos como si
fueran atributos. Se usa para controlar el acceso a los atributos de una clase,
proporcionando una interfaz más segura y flexible.
Los métodos get y set sí se incluyen, pero en Python se manejan de una forma más
elegante usando el decorador @property, que reemplaza los métodos tradicionales
get() y set() de otros lenguajes como Java o C++.

1️⃣Métodos get y set tradicionales (sin @property)


En otros lenguajes, se suelen definir métodos get y set de esta forma:

📌 Ejemplo: Usando get y set manualmente

python
CopiarEditar
class Persona:
def __init__(self, nombre):
self._nombre = nombre # Convención: "_" indica atributo
"privado"

def get_nombre(self):
return self._nombre

def set_nombre(self, nuevo_nombre):


if isinstance(nuevo_nombre, str): # Validación
self._nombre = nuevo_nombre
else:
raise ValueError("El nombre debe ser una cadena de texto")

persona = Persona("Carlos")
print(persona.get_nombre()) # "Carlos"

persona.set_nombre("Ana")
print(persona.get_nombre()) # "Ana"

✅ Desventajas:

 Es más verboso, ya que tenemos que escribir get_nombre() en vez de


persona.nombre.
 No es idiomático en Python, ya que Python tiene una mejor forma con @property.

2️⃣Reemplazo con @property (Estilo Pythonico ✅)


📌 Ejemplo: Usando @property para hacer un getter y setter elegante

python
CopiarEditar
class Persona:
def __init__(self, nombre):
self._nombre = nombre # Convención: "_" indica atributo privado

@property
def nombre(self):
return self._nombre # Getter

@nombre.setter
def nombre(self, nuevo_nombre):
if isinstance(nuevo_nombre, str): # Validación
self._nombre = nuevo_nombre
else:
raise ValueError("El nombre debe ser una cadena de texto")

persona = Persona("Carlos")
print(persona.nombre) # ✅ "Carlos" (Sin usar get_nombre())

persona.nombre = "Ana" # ✅ Asignación directa


print(persona.nombre) # ✅ "Ana"

# persona.nombre = 123 ❌ Error: "El nombre debe ser una cadena de texto"

✅ Ventajas de @property:

 Acceso como atributo (persona.nombre en vez de persona.get_nombre()).


 Se mantiene el encapsulamiento y validación con @setter.
 Código más limpio y Pythonico.

🔹 Problema propuesto:
Crea una clase CuentaBancaria con @property para saldo, asegurando que no pueda ser
negativo.

3️⃣Métodos get y set en @classmethod y @staticmethod


A veces, @property no es suficiente, y usamos @classmethod o @staticmethod para
gestionar atributos de clase en lugar de instancia.

📌 Ejemplo: Manejo de un atributo de clase con @classmethod

python
CopiarEditar
class Producto:
_iva = 0.16 # IVA del 16% como atributo de clase

@classmethod
def get_iva(cls):
return cls._iva # Getter de IVA

@classmethod
def set_iva(cls, nuevo_iva):
if 0 <= nuevo_iva <= 1:
cls._iva = nuevo_iva # Setter de IVA
else:
raise ValueError("El IVA debe estar entre 0 y 1")

print(Producto.get_iva()) # 0.16
Producto.set_iva(0.18) # Se cambia el IVA
print(Producto.get_iva()) # 0.18

✅ Observaciones:

 get_iva() y set_iva() son métodos de clase (@classmethod), porque afectan a


toda la clase.

🔹 Problema propuesto:
Crea una clase Banco con @classmethod para modificar la tasa de interés de todas las
cuentas.

🔹 Resumen
¿Se usa
¿Usa ¿Usa para
Métodos Decorador Ejemplo de uso
self? cls? atributos
de...?
get y set obj.get_nombre() /
Ninguno ✅ Sí ❌ No Instancia
tradicionales obj.set_nombre("Ana")
@property y obj.nombre / obj.nombre =
@setter
@property ✅ Sí ❌ No Instancia "Ana"
@classmethod ❌ No ✅ Sí Clase
@classmethod Clase.metodo()

@staticmethod @staticmethod ❌ No ❌ No
No accede a Clase.metodo()
nada

1️⃣Uso Básico de @property


📌 Ejemplo: Clase Circulo con un radio y su área calculada automáticamente

python
CopiarEditar
import math

class Circulo:
def __init__(self, radio):
self._radio = radio # Se usa _radio como atributo "privado"

@property
def radio(self):
return self._radio # Permite leer el radio

@property
def area(self):
return math.pi * self._radio ** 2 # Calcula el área sin
necesidad de un método adicional

circulo = Circulo(5)
print(circulo.radio) # 5
print(circulo.area) # 78.5398...

✅ Observaciones:

 @property convierte radio en un getter, permitiendo acceder a _radio como si fuera


un atributo.
 area es calculado automáticamente sin necesidad de llamarlo como un método
(circulo.area en lugar de circulo.area()).

🔹 Problema propuesto:
Crea una clase Cuadrado que tenga una propiedad lado y una propiedad perimetro.

2️⃣Uso de @property con @setter


📌 Ejemplo: Clase Persona con validación en la edad

python
CopiarEditar
class Persona:
def __init__(self, nombre, edad):
self._nombre = nombre
self._edad = edad # Se almacena en una variable "privada"

@property
def edad(self):
return self._edad # Getter

@edad.setter
def edad(self, nueva_edad):
if nueva_edad < 0:
raise ValueError("La edad no puede ser negativa")
self._edad = nueva_edad # Setter con validación

persona = Persona("Carlos", 25)


print(persona.edad) # 25
persona.edad = 30 # ✅ Se actualiza correctamente
print(persona.edad) # 30

# persona.edad = -5 ❌ Esto generará un error: "La edad no puede ser


negativa"

✅ Observaciones:

 @property define el getter (edad puede ser accedido como persona.edad).


 @edad.setter permite modificar la edad con validación.
 Si intentamos asignar una edad negativa, se lanza un error (ValueError).

🔹 Problema propuesto:
Crea una clase CuentaBancaria con una propiedad saldo que no permita valores
negativos.

3️⃣Uso de @property con @deleter


📌 Ejemplo: Clase Empleado que permite eliminar el atributo salario

python
CopiarEditar
class Empleado:
def __init__(self, nombre, salario):
self._nombre = nombre
self._salario = salario

@property
def salario(self):
return self._salario

@salario.deleter
def salario(self):
print("El salario ha sido eliminado")
del self._salario # Se elimina el atributo

empleado = Empleado("Ana", 4000)


print(empleado.salario) # 4000

del empleado.salario # Se elimina el salario


# print(empleado.salario) ❌ Error: el atributo ya no existe

✅ Observaciones:

 @salario.deleter permite eliminar el atributo salario.


 Al llamar del empleado.salario, el atributo desaparece.
🔹 Problema propuesto:
Crea una clase Producto con una propiedad precio que se pueda eliminar.

4️⃣@property con Cálculos Dinámicos


📌 Ejemplo: Clase Rectangulo con area y perimetro calculados automáticamente

python
CopiarEditar
class Rectangulo:
def __init__(self, base, altura):
self._base = base
self._altura = altura

@property
def base(self):
return self._base

@property
def altura(self):
return self._altura

@property
def area(self):
return self._base * self._altura

@property
def perimetro(self):
return 2 * (self._base + self._altura)

rectangulo = Rectangulo(10, 5)
print(rectangulo.area) # 50
print(rectangulo.perimetro) # 30

✅ Observaciones:

 area y perimetro son propiedades calculadas.


 Se pueden acceder sin usar () (rectangulo.area, no rectangulo.area()).

🔹 Problema propuesto:
Crea una clase Cilindro con propiedades volumen y superficie.

🔹 Resumen de @property en Python


Decorador Función

@property Convierte un método en un getter (se accede como un atributo).

@atributo.setter Permite modificar el valor de un atributo con validaciones.

@atributo.deleter Permite eliminar un atributo con del.

🚀 ¿Quieres más ejemplos o desarrollar algún problema propuesto? 😃

4o

Dijiste:
ahora sobre Decoradores @classmethod & staticmethod
ChatGPT dijo:

🔹 Decoradores @classmethod y @staticmethod en Python

Los decoradores @classmethod y @staticmethod permiten definir métodos especiales en


una clase sin necesidad de instancias específicas.

🔹 Diferencias clave:

Recibe Accede a
Recibe self
Decorador cls atributos/metodos de Se usa para...
(Instancia)
(Clase) clase

Métodos que afectan a toda


@classmethod ✅ Sí ❌ No ✅ Sí la clase, no a instancias
individuales.

Métodos independientes que


@staticmethod ❌ No ❌ No ❌ No están dentro de la clase por
organización.

1️⃣Uso de @classmethod
📌 Ejemplo: Crear instancias desde un método de clase

python
CopiarEditar
class Persona:
cantidad_personas = 0 # Atributo de clase
def __init__(self, nombre, edad):
self.nombre = nombre
self.edad = edad
Persona.cantidad_personas += 1 # Modifica el atributo de clase

@classmethod
def desde_cadena(cls, cadena):
nombre, edad = cadena.split("-")
return cls(nombre, int(edad)) # Crea y devuelve una instancia

@classmethod
def contar_personas(cls):
return f"Total de personas creadas: {cls.cantidad_personas}"

p1 = Persona("Juan", 30)
p2 = Persona.desde_cadena("Ana-25") # Usa @classmethod para crear una
instancia

print(p2.nombre) # "Ana"
print(Persona.contar_personas()) # "Total de personas creadas: 2"

✅ Observaciones:

 @classmethod usa cls para referirse a la clase en sí en lugar de la instancia.


 desde_cadena() crea un objeto sin necesidad de usar __init__ manualmente.
 contar_personas() accede y modifica el atributo de clase cantidad_personas.

🔹 Problema propuesto:
Crea una clase Coche con un método desde_lista(cls, lista) que cree instancias
desde una lista de datos.

2️⃣Uso de @staticmethod
📌 Ejemplo: Métodos auxiliares dentro de la clase

python
CopiarEditar
class Utilidad:
@staticmethod
def es_par(numero):
return numero % 2 == 0 # Devuelve True si es par

@staticmethod
def sumar(a, b):
return a + b # Simplemente suma dos números

print(Utilidad.es_par(4)) # True
print(Utilidad.sumar(10, 20)) # 30

✅ Observaciones:
 @staticmethod no recibe cls ni self, es totalmente independiente.
 Se usa cuando no se necesita acceder a atributos de clase ni de instancia.
 es_par() y sumar() son funciones normales dentro de la clase, pero no dependen de
instancias.

🔹 Problema propuesto:
Crea una clase Conversor con un método celsius_a_fahrenheit(temp) que convierta
temperaturas.

3️⃣Comparación @classmethod vs @staticmethod


📌 Ejemplo: Fábrica de Productos

python
CopiarEditar
class Producto:
impuesto = 1.21 # IVA del 21%

def __init__(self, nombre, precio):


self.nombre = nombre
self.precio = precio

@classmethod
def cambiar_impuesto(cls, nuevo_impuesto):
cls.impuesto = nuevo_impuesto # Cambia el impuesto global

@staticmethod
def calcular_precio_con_iva(precio):
return precio * 1.21 # Solo realiza el cálculo, sin modificar
atributos

print(Producto.calcular_precio_con_iva(100)) # 121.0
Producto.cambiar_impuesto(1.18) # Cambia el IVA a 18%
print(Producto.impuesto) # 1.18

✅ Observaciones:

 @classmethod cambia el IVA de toda la clase (cambiar_impuesto).


 @staticmethod solo hace un cálculo sin afectar la clase
(calcular_precio_con_iva).

🔹 Problema propuesto:
Crea una clase Banco con un método ajustar_tasa_interes(cls, nueva_tasa) y otro
método calcular_interes(monto, tasa).
4️⃣Combinación de @property, @classmethod y @staticmethod
📌 Ejemplo: Cuenta Bancaria

python
CopiarEditar
class CuentaBancaria:
tasa_interes = 0.05 # 5% de interés anual

def __init__(self, titular, saldo):


self.titular = titular
self._saldo = saldo # Atributo privado

@property
def saldo(self):
return self._saldo # Getter

@classmethod
def cambiar_tasa_interes(cls, nueva_tasa):
cls.tasa_interes = nueva_tasa # Cambia la tasa para todas las
cuentas

@staticmethod
def calcular_interes(monto, tasa):
return monto * tasa # Solo realiza un cálculo matemático

cuenta = CuentaBancaria("Luis", 1000)


print(cuenta.saldo) # 1000
CuentaBancaria.cambiar_tasa_interes(0.07) # Cambia el interés a 7%
print(CuentaBancaria.tasa_interes) # 0.07
print(CuentaBancaria.calcular_interes(1000, 0.07)) # 70

✅ Observaciones:

 @property protege el saldo.


 @classmethod cambia la tasa de interés para todas las cuentas.
 @staticmethod hace un cálculo matemático independiente.

🔹 Problema propuesto:
Crea una clase Empleado con un método cambiar_sueldo_minimo(cls, nuevo_sueldo)
y otro método calcular_bono(sueldo, porcentaje).

🔹 Resumen de @classmethod y @staticmethod


¿Usa ¿Usa ¿Modifica la ¿Modifica
Decorador Uso recomendado
cls? self? clase? instancias?
@classmethod ✅ Sí ❌ No ✅ Sí ❌ No Métodos que afectan a la clase
¿Usa ¿Usa ¿Modifica la ¿Modifica
Decorador Uso recomendado
cls? self? clase? instancias?

completa.

Métodos independientes sin


@staticmethod ❌ No ❌ No ❌ No ❌ No
acceso a la clase ni a instancias.

🚀 ¿Te gustaría que desarrolle alguno de los problemas propuestos? 😃

4o

Buscar

Reason

También podría gustarte