- sobrecarga de métodos no existe en Python
clases
Para establecer las propiedades (o atributos) de un objeto dentro de una clase, normalmente usas el método especial __init__() que vendría a ser el constructor . Aquí definiremos las propiedades iniciales del objeto utilizando el parámetro self.
class MiClase:
def __init__(self):
print("Creando objeto de MiClase")
objeto = MiClase()
# Salida: Creando objeto de MiClase
método constructor
En otros lenguajes el nombre de la clase es el mismo que el del metodo constructor , en python no pasa esto se usa __init__
__init__es el método constructor especial que se ejecuta automáticamente cuando se crea un nuevo objeto de una clase. Su función es inicializar los atributos del objeto
Objetos
¿Qué es self?
selfes una referencia al objeto actual que está invocando el método.- Es el primer parámetro en los métodos de instancia de una clase, y permite acceder a los atributos y métodos de ese objeto en particular.
class Persona:
def __init__(self, nombre, edad):
self.nombre = nombre
self.edad = edad
self.nota="solo se pone como paso de parametros lo valores que se pasan si inicializamos aqui una variable no hace falta ponerlo en paso de parametros, por ejemplo nota no iria"
def saludar(self): print(f"Hola, soy{self.nombre} y tengo {self.edad} años.")
nota Si no haces self.nombre = nombre, el valor de nombre no quedará guardado en la instancia del objeto. Por lo tanto, no podrás acceder a ese valor después de la creación del objeto.
nota para trabajar con propiedades dentro de un metodo debemos de pasar como parámetro el self y asi poder acceder a las propiedades. Osea que todos los metodos al nivel del objeto se van a pasar como parametro el self y en el cuerpo del metodo accederemos a cierta propiedad con la nomeclatura del punto self.nombreAtributo
ejemplo de metodos a nivel de objeto
Creación objetos
Cuando creas una instancia de la clase Persona, self permite acceder y modificar los atributos (nombre y edad) específicos de esa instancia.
persona1 = Persona("Jordan", 28)
persona2 = Persona("Ana", 22)
# Llamar a los métodos
persona1.saludar() # Salida: Hola, soy Jordan y tengo 28 años.
persona2.saludar() # Salida: Hola, soy Ana y tengo 22 años.
Métodos de clase y variable de clase (requieren cls en lugar de self)
En lugar de operar sobre una instancia de la clase self , operan sobre la clase en sí misma. En lugar de usar self, usan cls como primer parámetro (una referencia a la clase en lugar del objeto).
- Requieren cls como primer parámetro, en lugar de self, y se declaran con el decorador @classmethod.
- las variables a nivel de clase solo se ponen fuera del método como esta en el próximo código de ejemplo.
y para que me sirve esto?:
- Cuando necesitas trabajar con datos que pertenecen a la clase y no a una instancia en particular.
- Por ejemplo, si tienes un contador de cuántas instancias de la clase se han creado, o si necesitas crear un método que afecte a todas las instancias de la clase.
- También es útil cuando tienes que crear constructores alternativos que crean objetos de una forma diferente a la del constructor principal (__init__).
class Persona:
# Variable de clase (compartida por todas las instancias)
num_personas = 0
def __init__(self, nombre):
self.nombre = nombre
# Incrementa el contador de la clase cada vez que se crea una instancia
Persona.num_personas += 1
# Método de clase que opera sobre la clase
@classmethod
def total_personas(cls):
return f"Total de personas creadas: {cls.num_personas}"
Métodos estáticos (staticmethod)
El método estático en Python, definido con el decorador @staticmethod, es un método que no necesita acceso ni a la instancia (self) ni a la clase (cls). Es decir, no depende ni de los atributos de la instancia ni de los de la clase.
Si es raro y es dificil para mi ahora encontrarle una utilidad pero solo ten la idea de que un metodo estatico no usa las funcionalidades ni propiedades de los objetos ni de la clase es un ser independiente de si mismo. ejemplo:
class Matematicas:
@staticmethod
def sumar(a, b):
return a + b
@staticmethod
def restar(a, b):
return a - b
Aquí tienes operaciones matemáticas agrupadas en la clase Matematicas. No es necesario que estas funciones accedan a algún atributo de la clase, pero su organización dentro de Matematicas hace que todo esté más claro.
Encapsulamiento
En Python, puedes aplicar encapsulamiento usando niveles de visibilidad:
- Público (por defecto, sin guión bajo): son accesibles desde cualquier lugar
- Protegido (un guión bajo,
_atributo): no se usa - Privado (dos guiones bajos,
__atributo):no pueden ser accedidos directamente desde fuera de la clase
Getters y Setters
class Coche:
def __init__(self, marca):
self.__marca = marca # Atributo privado
def get_marca(self): # Getter
return self.__marca
def set_marca(self, nueva_marca): # Setter
self.__marca = nueva_marca
coche = Coche("Toyota")
print(coche.get_marca()) # Acceso controlado a través del getter
coche.set_marca("Honda") # Modificar el valor a través del setter
print(coche.get_marca()) # Ahora es "Honda"
También podemos encapsular métodos - esto es util para usar metodos dentro de otros metodos que estan en la clase misma clase.
class Coche:
def __encender_bateria(self): # Método privado
print("Batería encendida.")
def __activar_sistema_electrico(self): # Método privado
print("Sistema eléctrico activado.")
def arrancar(self): # Método público que controla el flujo
self.__encender_bateria()
self.__activar_sistema_electrico()
print("Coche encendido.")
coche = Coche()
coche.arrancar() # Se accede solo al método público
Herencia
se da cuando una clase copia a otra clase, heredando sus propiedades y metodos para luego diferenciarse desarrollando sus propios metodos y funcionalidades usando como base la clase padre que heredo. (ejemplo: perro hereda de animal.)
# Definimos una clase padre
class Animal:
pass
# Creamos una clase hija que hereda de la padre
class Perro(Animal):
pass
Uso de super()
La función super() nos permite acceder a los métodos de la clase padre desde una de sus hijas. Volvamos al ejemplo de Animal y Perro.
# Clase base (superclase)
class Vehiculo:
def __init__(self, marca, modelo):
self.marca = marca
self.modelo = modelo
def arrancar(self):
print(f"El {self.marca} {self.modelo} está arrancando.")
# Clase derivada (subclase)
class Coche(Vehiculo):
def __init__(self, marca, modelo, color):
# Llamamos al constructor de la clase base para reutilizar marca y modelo
super().__init__(marca, modelo)
self.color = color
def tocar_claxon(self):
print(f"El coche {self.marca} está tocando el claxon.")
# Crear una instancia de la subclase
mi_coche = Coche("Toyota", "Corolla", "Rojo")
# Usamos métodos de la clase base y subclase
mi_coche.arrancar() # Método heredado de la clase Vehiculo
mi_coche.tocar_claxon() # Método propio de la clase Coche
Uso de isinstance()
Herencia múltiple
Python permite que una clase herede de más de una clase, lo que se conoce como herencia múltiple. Sin embargo, hay que tener cuidado con ella, ya que puede llevar a situaciones complicadas. Aquí un ejemplo simple:
class Vehiculo:
def moverse(self):
print("El vehículo se está moviendo.")
class Avion:
def volar(self):
print("El avión está volando.")
class Avioneta(Vehiculo, Avion):
pass
mi_avioneta = Avioneta()
mi_avioneta.moverse() # Hereda el método de Vehiculo
mi_avioneta.volar() # Hereda el método de Avion
nota un posible problema que se nos puede presentar en la herencia multiple es que al momento de crear un objeto con la clase que hereda de 2 padres, tendremos que lidiar con la existencia de 2 constructores, y aqui nace la pregunta, que chucha hacer?
pues eso es sencillo de contestar, esto depende de quien esta primero
- class Avioneta(Vehiculo, Avion) en este ejemplo tenemos primero Vehiculo, entonces se le va a otorgar prioridad al constructor Vehículo, ese es el que sera aplicado.
Sobrescrita de métodos
Las subclases pueden sobrescribir los métodos de la superclase si necesitan un comportamiento diferente. Veamos cómo hacer eso:
sobreescribiendo completamente el metodo: solo ponemos el mismo nombre y lo que queremos que haga, lo mas comun es que si queremos usar la funcionalidad del padre y añadir algo mas, solo copiamos y pegamos el codigo al hijo para despues poner ese agregado.
class Vehiculo:
def arrancar(self):
print("El vehículo está arrancando.")
class Coche(Vehiculo):
def arrancar(self):
print("El coche está arrancando.")
# Crear una instancia de la subclase
mi_coche = Coche()
mi_coche.arrancar() # Sobrescribe el método de Vehiculo
Polimorfismo
[[Duck Typing]]