Cuando trabajas con programación orientada a objetos en Python, los decoradores se convierten en herramientas esenciales para añadir funcionalidad específica a los métodos de tus clases. Comprender cuándo y cómo usar @staticmethod, @classmethod y @property marca la diferencia entre un código funcional y uno verdaderamente profesional.
¿Cómo funciona el decorador static method en Python?
El decorador @staticmethod se utiliza cuando un método no accede ni modifica información de la clase [0:24]. Esto quiere decir que no interactúa con atributos ni con otros métodos del objeto. Un ejemplo claro es una clase Calculadora con un método sumar que recibe dos parámetros enteros (a y b) y retorna directamente a + b.
python
class Calculadora:
@staticmethod
def sumar(a: int, b: int) -> int:
return a + b
El método no necesita self porque no depende del estado del objeto.
Recibe información desde el exterior sin interactuar con la clase.
Es ideal para operaciones utilitarias que no requieren contexto de instancia.
¿Cuándo usar class method para modificar atributos de clase?
A diferencia de static method, el decorador @classmethod se aplica cuando el método modifica algún aspecto de la clase [1:18]. El primer parámetro que recibe es cls, que representa a la propia clase.
python
class Contador:
count = 0
@classmethod
def incrementar(cls): cls.count+=1
Al llamar Contador.incrementar() dos veces y luego imprimir Contador.count, el resultado es 2 [2:13]. Esto confirma que el método está modificando el atributo count que pertenece a la clase, no a una instancia particular.
Se usa cls en lugar de self para hacer referencia a la clase.
Permite modificar atributos compartidos entre todas las instancias.
Se invoca directamente sobre la clase, sin necesidad de crear un objeto.
¿Qué hace el decorador property y cómo actúa como getter y setter?
El decorador @property permite acceder a la funcionalidad de un método como si fuera un atributo de clase [2:33]. Esto significa que al llamarlo no se usan paréntesis, se accede con el punto directamente.
¿Cómo se implementa property como getter?
Consideremos una clase Circulo que recibe un radio de tipo flotante en su constructor [2:50]:
python
class Circulo:
def init(self, radio: float):
self._radio = radio
Al crear c = Circulo(5) e imprimir c.area, obtenemos el resultado sin usar paréntesis [3:52]. La convención de agregar un guion bajo (_radio) permite diferenciar entre el atributo interno y el método que lo expone.
¿Cómo se usa property como setter para validar datos?
Para modificar información se utiliza la variante setter del decorador [4:22]. Se define colocando @radio.setter sobre un nuevo método con el mismo nombre:
python
@radio.setter
def radio(self, valor: float):
if valor < 0:
raise ValueError("El radio no puede ser negativo")
self._radio = valor
Si asignas c.radio = 10, el área se recalcula correctamente con el nuevo valor [4:56].
Si asignas c.radio = -10, Python levanta un ValueError con el mensaje personalizado [5:17].
Esta técnica de validación dentro del setter es fundamental para mantener la integridad de los datos en tus objetos.
¿Por qué estos decoradores hacen tu código más profesional?
Cada uno de estos decoradores ya viene integrado en Python, por lo que no necesitas crearlos, solo invocarlos [5:35]. Su uso correcto aporta claridad y estructura:
@staticmethod: para métodos independientes del estado de la clase.
@classmethod: para métodos que modifican atributos a nivel de clase.
@property: para exponer métodos como atributos, tanto en lectura (getter) como en escritura (setter).
Dominar estos tres decoradores te permitirá escribir clases más limpias y con un comportamiento controlado. ¿Ya los estás aplicando en tus proyectos? Comparte tu experiencia en los comentarios.
Decoradores en Programación Orientada a Objetos en Python
En Python, los decoradores no solo se usan en funciones, también se pueden aplicar a clases y métodos para extender o modificar su comportamiento. Los decoradores en clases y métodos son especialmente útiles para aspectos transversales como la validación de permisos, el registro de accesos, el manejo de excepciones y la administración de cachés.
Aquí tienes una guía rápida sobre cómo funcionan y un ejemplo detallado:
### Decoradores en Métodos de Clase
Los decoradores pueden aplicarse a métodos específicos de una clase, y se comportan según el tipo de método:
- **Métodos de instancia** (los métodos normales que acceden a self).
- **Métodos de clase** (aquellos que usan @classmethod y acceden a cls).
- **Métodos estáticos** (usando @staticmethod, no acceden ni a self ni a cls).
Los decoradores en métodos de clase pueden hacer cosas como:
1. Controlar permisos antes de ejecutar el método.
2. Hacer un registro (logging) cada vez que se llama al método.
3. Manejar errores de forma consistente.
### Decoradores en Clases
Un decorador en una clase modifica el comportamiento de la clase en su conjunto, normalmente para extenderla o agregarle nuevas funcionalidades.
### Ejemplo de Uso
Imaginemos una clase CuentaBancaria donde queremos aplicar un decorador para registrar cada vez que se realiza una operación, y otro decorador para comprobar permisos de acceso a ciertas operaciones.
from functools import wraps
import datetime
\# Decorador para verificar permisos
def verificar\_permisos(permiso\_necesario):  def decorador\_metodo(func):  @wraps(func)  def envoltura(self, \*args, \*\*kwargs):  if permiso\_necesario not in self.permisos:  raise PermissionError(f"No tienes permisos para realizar esta operación: {permiso\_necesario}")  return func(self, \*args, \*\*kwargs)  return envoltura  return decorador\_metodo
\# Decorador para registrar en log
def registrar\_operacion(func):  @wraps(func)  def envoltura(self, \*args, \*\*kwargs):  resultado = func(self, \*args, \*\*kwargs)  operacion = f"{func.\_\_name\_\_} ejecutado el {datetime.datetime.now()}"  self.historial.append(operacion)  print(f"Registro: {operacion}")  return resultado  return envoltura
\# Clase CuentaBancaria usando decoradores en sus métodos
classCuentaBancaria:  def \_\_init\_\_(self, balance=0):  self.balance = balance  self.historial = \[]  self.permisos = \['ver\_balance', 'retirar'] # permisos actuales del usuario  @registrar\_operacion  @verificar\_permisos('ver\_balance')  def ver\_balance(self):  print(f"Balance actual: ${self.balance}")  return self.balance  @registrar\_operacion  @verificar\_permisos('retirar')  def retirar(self, cantidad):  if cantidad > self.balance:  raise ValueError("Fondos insuficientes")  self.balance -= cantidad  print(f"Retiro exitoso: ${cantidad}. Nuevo balance: ${self.balance}")  return self.balance
\# Uso de la clase con decoradores
cuenta = CuentaBancaria(1000)
\# Operaciones
cuenta.ver\_balance()cuenta.retirar(200)
\# Intento de retiro sin permisos
try:  cuenta.permisos.remove('retirar')  cuenta.retirar(100)except PermissionError as e:  print(e)
### Explicación
1. **@verificar\_permisos**: Este decorador toma un parámetro, permiso\_necesario, y se asegura de que el usuario tenga el permiso adecuado antes de ejecutar el método.
2. **@registrar\_operacion**: Este decorador registra cada operación realizada, almacenándola en el atributo historial.
Este patrón es muy poderoso para clases que requieren varias verificaciones y registros en sus métodos, proporcionando una estructura de código limpia y modular.
gracias por la aportacion
Gracias por tu aporte!
creo, que solo lanza ejemplos muy al aire, tan solo no probo el ejemplo de calculadora... solo dejo al aire la idea. Parece que no hay una estructura en los conceptos que explica.
Ha sido una constante en todo el curso. Diría que un 40-50% me lo ha explicado chatgpt.
sí, coincido contigo... tenía que haber explicado que la clase calculadora con @staticmethod sólo sirve ahí como clasificador o etiqueta de funciones como para no perderlas de vista en el código, podía haber añadido otros def de matemática para que quedara claro, esta es la explicación de chatgpt: Porque a veces organizar lógicamente funciones relacionadas dentro de una clase mejora la claridad, sobre todo en proyectos grandes. Es una forma de agrupar funciones coherentes.
En Python, property y setter son decoradores que permiten gestionar el acceso a los atributos de una clase de forma controlada.
property: Este decorador permite acceder a un método como si fuera un atributo. Por ejemplo, si tenemos un método que calcula el área de un círculo, al usar property, podemos acceder a este método sin paréntesis, como si fuera un atributo.
setter: Se usa para definir un método que permite modificar el valor de un atributo de forma segura. Por ejemplo, puedes validar que el nuevo valor no sea negativo antes de asignarlo a un atributo.
Estos decoradores ayudan a encapsular la lógica de la clase y proporcionan un control más estricto sobre cómo se accede y modifica la información.
Gracias por tu aporte!
No termino de entender para qué usar decoradores, por ejemplo, en el ejemplo del área del círculo, por que no sencillamente no se crea un atributo como self.area = (radius**2)*3.1416 y ya, los atributos extienden la funcionalidad sin embargo no veo la razón de usarlos si simplemente se pueden dar esas características y funciones a la clase y ya.
@property Facilita el acceso y la modificación de atributos de manera controlada, permitiendo la validación y el encapsulamiento.
A mi modo de ver, este decorador tiene dos ventajas: 1. Poder convertir el resultado de un método en un atributo y 2. Poder tener este atributo de manera interna y más privada.
alguien tiene informacion de los decoradores?
no he entendido nada, como funcionan?
Un decorador es una función que se ejecuta antes de la función al que se la asignas.
#Ejemplo
def tieneDinero():
@tieneDinero
def comprar():
Antes de ejecutar comprar el decorador con la función tieneDinero se ejecuta antes y ahi puedes escribir la lógica que desees, el uso más común es de validar y formatear datos, pero lo puedes usar para lo que sea.
Creo que no es algo que si no se entiende o se usa a la primera esté mal. Por ahora, veo estos decoradores como formas en el que el código está "mejor" escrito. Algo más "profesional", mejor visto para los profesionales
No, no se puede utilizar el decorador @nombre_del_metodo.setter sin haber definido previamente el decorador @property para ese mismo método. El decorador @property convierte el método en un atributo, lo que permite el uso del decorador @setter para modificar su valor. Esto es fundamental en Python para garantizar que se mantenga la consistencia y el control sobre la asignación de valores a los atributos de la clase.
Hola! Siento que el contenido es bastante completo sin embargo veo que muchas clases son mas un ejemplo en el que se aplican conceptos que no se están dando, sé que gran parte es autoaprendizaje pero es muy difícil si inicialmente no se da una sintaxis, un por qué se usa y al final si el ejemplo, solo siento que es un repaso y en mi caso solo entiendo esos ejemplos cuando son temas que yo domino, más que queja lo comento para cursos futuros ya que lo ideal no es entrar aquí para salir a buscar toda la teoría en otras fuentes.
Estoy de acuerdo, esta clase en especifico estuvo muy mal explicada, en lugar de explicar cada uno de los decoradores y luego poner un ejemplo de caso de uso real donde implemente los mismos, solo se limito a escribir el codigo y no explico nada. Si solo quisiera ver ejemplo, se lo podria preguntar a ChatGPT. Además, en mi caso tengo experiencia en otros lenguajes, pero hay muchos que básicamente están aprendiendo a programar con este curso.
Todo en esta clase esta mal explicado. Lo que entendí:
@staticmethod te brinda la posibilidad de crear un método estático, es decir, que no necesitas crear una instancia de la clase para usar el método. Util para tener métodos agrupados para unac misma funcionalidad, pero que no necesiten acceder a información interna de la clase.
El @classmethod se usa cuando necesitas que el método tenga acceso a la clase (usando cls) en lugar de a un objeto específico (self). Es ideal para gestionar un estado compartido por todas las instancias (atributos de clase)
@property permite convertir un método en un "atributo virtual" o "computado". Es decir, puedes acceder a un método como si fuera una variable normal, sin usar paréntesis ()
@radius.setter se utiliza para definir el comportamiento de la aplicación de un nuevo valor al atributo "virtual" en este caso radius. Para usarlo se tiene que haber definido antes un atributo virtual con @property
Donde radica la diferencia entre usar o no un Decorador en una clase?
La diferencia radica en la claridad y la intención que aportan los decoradores.
Sin decoradores como @staticmethod o @classmethod, los métodos se comportan como métodos de instancia por defecto. Esto significa que siempre reciben self como primer argumento, incluso si no lo usan.
Los decoradores explicitan el propósito del método:
@staticmethod: Indica que el método no depende de la instancia ni de la clase.
@classmethod: Señala que el método opera sobre la clase (cls) y no sobre una instancia específica.
Esto hace el código más legible y previene errores.
Alguien me podría comentar la diferencia entre llamar al atributo self.radius y self._radius?
No entiendo muy bien por qué se coloca el guion previo al nombre del atributo.
Muy buen punto y observación.
Respuesta:
En Python, es común usar un prefijo como _ en los atributos de instancia para diferenciarlos de los parámetros del constructor. En el ejemplo, radius es el parámetro del método __init__, mientras que self._radius es el atributo que guarda el valor. Esto evita confusiones y permite reconocer fácilmente que _radius es un atributo de la instancia. Esta convención facilita el acceso y la modificación del atributo dentro de la clase sin conflictos con los parámetros pasados al constructor.
Espero haber sido claro, sino con mucho gusto trato de explicarlo mejor. Saludos.
Decoradores predefinidos como el @staticmethod : existe incluso antes de cualquier instancia de la clase, @classmethod: hacen modificacion del estado de la clase
,@propperti : permite que los metodos se comporten como atributos aplicando encapsulamiento
son especialmente
decoradores de biblioteca como: @functools.wraps @lru_cache @contextManager, @dataclass
proporcionan funcionalidades adicionales y optimizaciones
decoradores personalizados pueden usarse para registro validaciones o timers
Decoradores que incluye python: Decoradores para Métodos en Clases
@staticmethodpythonCopiar códigoclass MiClase:
@staticmethod def metodo_estatico():
print("Este es un método estático.")
MiClase.metodo_estatico()
Convierte un método en un método estático.
El método estático no recibe ni self ni cls como argumento.
Se utiliza para definir funciones relacionadas con la clase, pero que no dependen de una instancia.
Ejemplo:
@classmethodpythonCopiar códigoclass MiClase:
@classmethod def metodo_clase(cls):
print("Este es un método de clase.")
MiClase.metodo_clase()
Convierte un método en un método de clase.
Recibe cls como primer argumento, que representa la clase (no la instancia).
Se utiliza cuando se necesita acceder a atributos o métodos de clase.
Ejemplo:
@propertypythonCopiar códigoclass MiClase:
def __init__(self, valor):
self._valor = valor
@property def valor(self):
return self._valor
obj = MiClase(10)
print(obj.valor) # Accede al atributo con lógica adicional.
Convierte un método en un getter para un atributo.
Se utiliza para acceder a atributos como si fueran propiedades, lo que permite definir lógica adicional al obtener un valor.
Ejemplo:
@<property>.setterpythonCopiar códigoclass MiClase:
def __init__(self, valor):
self._valor = valor
@property def valor(self):
return self._valor
@valor.setter def valor(self, nuevo_valor):
self._valor = nuevo_valor
obj = MiClase(10)
obj.valor = 20 # Cambia el valor con lógica adicional.print(obj.valor)
Permite definir un setter para un atributo, utilizado para establecer valores con lógica adicional.
Ejemplo:
@<property>.deleterpythonCopiar códigoclass MiClase:
def __init__(self, valor):
self._valor = valor
@property def valor(self):
return self._valor
@valor.deleter def valor(self):
del self._valor
obj = MiClase(10)
del obj.valor # Lógica al eliminar.
Permite definir un deleter para un atributo, utilizado para eliminar valores con lógica adicional.
Ejemplo:
Decoradores para Corrutinas y Generadores
@asyncio.coroutine(obsoleto en Python 3.10)
Usado para definir funciones generadoras asíncronas en versiones anteriores de Python.
Especifica diferentes firmas de funciones para sobrecarga de funciones (solo para propósitos de tipado).
Los modificadores utilizados en el contexto de decoradores en Programación Orientada a Objetos en Python son:
@staticmethod: Se utiliza para definir un método que no accede a la instancia o clase.
@classmethod: Permite modificar la clase o acceder a atributos de clase, en vez de a la instancia.
@property: Facilita acceder a un método como si fuera un atributo, permitiendo también la creación de setters.
Estos decoradores ayudan a estructurar el código y a mantener buenas prácticas en programación orientada a objetos.
Esto lo redactaste con AI bro jajajaja
Debes usar el decorador @staticmethod en Python. Este decorador se aplica a un método que no requiere acceso a la instancia (self) ni a la clase (cls). Los métodos estáticos son útiles para agrupar funciones relacionadas con la clase, pero que no necesitan acceder a sus atributos ni modificar su estado.
Esto ya se podría considerar como avanzado?
La clase prepara para escribir código Pythonico y profesional, es momento de dar un paso más y enfrentar desafíos más complejos.
```js
def decorador_clase(cls):
cls.autor = "Ingeniero de Datos"
return cls
@decorador_clase
class Informe:
pass
print(Informe.autor)
Me parece algo complejo de entender, pero lo poco que comprendí es que los decoradores funcionan como una función que se realiza antes de realizar la función original.
Lo tomo como si en el ordenador cuando nosotros queremos eliminar algún archivo nos salta una ventana de alerta para preguntarnos si estamos seguros.
En este caso la función original seria la de eliminar el archivo y el decorador como la ventana emergente de alerta.
Me podrían confirmar si estoy en lo cierto o me estoy equivocando por favor.
¿Qué decorador se utiliza para métodos que no acceden a la información de la clase?
A) @classmethod
B) @staticmethod (Correcta)
C) @property
D) @decorador
¿Cuál de los siguientes decoradores permite modificar atributos de la clase?
A) @staticmethod
B) @classmethod (Correcta)
C) @property
D) @decorador
¿Qué decorador se utiliza para acceder a métodos como si fueran atributos?
A) @staticmethod
B) @classmethod
C) @property (Correcta)
D) @decorador
En el contexto de la clase Calculadora, ¿qué tipo de datos recibe el método sumar?
A) Flotantes
B) Cadenas
C) Enteros (Correcta)
D) Listas
¿Qué error se levanta cuando se intenta asignar un valor negativo al radio en la clase Círculo?
A) ValueError (Correcta)
B) TypeError
C) AttributeError
D) IndexError
¿Qué método se utiliza para incrementar un contador en la clase Contador?
A) increment
B) add
C) count (Correcta)
D) sum
¿Cómo se define el decorador para un método de clase?
A) @staticmethod
B) @classmethod (Correcta)
C) @property
D) @decorador
¿Qué valor retorna el método área en la clase Círculo?
A) El radio
B) 3.14 * radio^2 (Correcta)
C) Un número entero
D) Un string
¿Qué función cumple el decorador @property en un método setter?
A) Modifica un atributo (Correcta)
B) Solo devuelve un valor
C) Define un método estático
D) No tiene función
¿Qué se puede concluir sobre el uso de decoradores en Python?
A) Son opcionales
B) Ayudan a extender funcionalidades (Correcta)
C) Son obsoletos
D) Solo se usan con funciones
quede muy perdido en esta clase!!!
creo que la metodologia de esta clase o la de toda la seccion de decoradores puede mejorarse porque hay muchos vacios y deja mucho hueco solo lo explica superficialmente y creo que es tema algo complejo
Si es bastante complejo, y creo que si lo explicara más a fondo la clse se alargaria mucho o incluso podria tomar varias clases, por eso me parece que solo te sueltan el tema para que lo conoscas y luego tu lo profundices por tu cuenta
Analogía para los que sepan algo de SQL y quieran entender como funciona @radius.setter ⇒
Un @<nombre_propiedad>.setter se comporta de manera muy similar a un trigger en una base de datos. Un trigger es un bloque de código que se ejecuta automáticamente en respuesta a ciertos eventos (como la inserción, actualización o eliminación de datos).
De la misma manera, el método decorado con @<nombre_propiedad>.setter se "dispara" o se ejecuta automáticamente cuando se intenta asignar un valor al atributo correspondiente de un objeto de la clase.
Y al igual que los triggers en bases de datos pueden realizar diversas acciones (verificar la integridad de los datos, actualizar otras tablas, registrar eventos, etc.), el setter en Python puede contener cualquier lógica que necesites ejecutar en el momento en que se modifica el valor del atributo:
Verificar: Como en el ejemplo del radio positivo.
Transformar: Como capitalizar un nombre o eliminar espacios.
Actualizar otros atributos: Como recalcular el área de un rectángulo.
Registrar (logging): Dejar constancia de la modificación.
Emitir eventos: Notificar a otras partes del sistema sobre el cambio.
Incluso "eliminar" (aunque esto sería menos común y más conceptual, podrías, por ejemplo, establecer una bandera interna o realizar otra acción en respuesta a un valor específico).
En resumen:
El @<nombre_propiedad>.setter actúa como un mecanismo de interceptación o un trigger que se activa cuando se intenta cambiar el valor de un atributo específico, permitiéndote ejecutar código personalizado en ese momento.