Fundamentos de Programación y Python

1

¿Por qué aprender Python?

2

Introducción a Python

3

Conceptos Básicos de Programación

4

Práctica: Te doy la bienvenida a los ejercicios interactivos

5

Manipulación de Cadenas de Texto en Python

6

Enteros, Flotantes y Booleanos

7

Todo lo que Debes Saber sobre print en Python

8

Operaciones Matemáticas en Python

9

Operaciones de Entrada/Salida en Consola

Colección y Procesamiento de Datos en Python

10

Listas

11

Método slice

12

Listas de más dimensiones y Tuplas

13

Aplicación de Matrices

14

Diccionarios

15

Comprehension Lists en Python (CLASE NUEVA)

Control de Flujo en Python

16

Estructuras condicionales

17

Bucles y Control de Iteraciones

18

Generadores e Iteradores

Funciones y Manejo de Excepciones en Python

19

Uso de Funciones en Python

20

Funciones Lambda y Programación Funcional en Python

21

¿Cómo realizar una función recursiva en Python?

22

Manejo de Excepciones y Uso de Pass (CLASE NUEVA)

Programación Orientada a Objetos en Python

23

Fundamentos de Programación Orientada a Objetos en Python

24

Ejercicio Biblioteca con POO

25

Herencia en POO con Python

26

Objetos heredados

27

Los 4 pilares de la programacion orientada a objetos

28

Uso de super() en Python (CLASE NUEVA)

29

Superando los Fundamentos de Programación Orientada a Objetos en Python

Lectura y escritura de archivos

30

Manejo de Archivos .TXT (CLASE NUEVA)

31

Manejo de Archivos CSV (CLASE NUEVA)

32

Manejo de Archivos JSON (CLASE NUEVA)

Biblioteca estándar de Python

33

Biblioteca estándar en Python (CLASE NUEVA)

34

Librería Os, Math y Random (CLASE NUEVA)

35

Librería Statistics y Análisis Estadístico (CLASE NUEVA)

36

Proyecto final: Guerra naval

Conceptos avanzados de Python

37

Recapitulación de lo aprendido hasta ahora

38

Escribir código Pythonico y profesional

39

Comentarios y Docstrings en Python

40

Scope y closures: variables locales y globales

41

Anotaciones de tipo

42

Validación de tipos en métodos

43

Librería Collections y Enumeraciones

Decoradores

44

Decoradores en Python

45

Decoradores anidados y con parámetros

46

Uso de Decoradores en clases y métodos

Métodos y estructura de clases en Python

47

Métodos mágicos

48

Sobrecarga de operadores

49

Implementación de `if __name__ == "__main__":`

50

Metaprogramación en Python

51

Uso de *args y **kwargs

52

Métodos privados y protegidos

53

Gestión avanzada de propiedades

54

Métodos estáticos y de clase avanzados

Programación concurrente y asíncrona

55

Introducción a la concurrencia y paralelismo

56

Threading y multiprocessing en Python

57

Asincronismo con asyncio

58

Asincronismo y concurrencia

Creación de módulos y paquetes

59

Creación de módulos en Python

60

Gestión de paquetes

61

Publicación de paquetes en PyPI

Proyecto final

62

Implementación de un sistema completo

63

Implementación de un Sistema Completo

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Curso de Python

Curso de Python

Carli Code

Carli Code

Decoradores anidados y con parámetros

45/63
Recursos

Aportes 11

Preguntas 1

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

CON PARAMETROS VS ANIDADOS 1\. Propósito y Uso: • Decoradores con Parámetros: Se utilizan cuando necesitas pasar parámetros adicionales al decorador, permitiendo personalizar su comportamiento. • Decoradores Anidados: Se usan para aplicar múltiples decoradores secuencialmente, añadiendo capas de funcionalidad a la función. 2\. Complejidad de la Estructura: • Decoradores con Parámetros: Requieren una función externa adicional para manejar los parámetros. • Decoradores Anidados: Implican aplicar múltiples decoradores uno encima de otro, pero cada decorador sigue la estructura básica de un decorador. 3\. Nivel de Control: • Decoradores con Parámetros: Ofrecen un control más fino sobre la lógica del decorador debido a los parámetros adicionales. • Decoradores Anidados: Permiten combinar varios decoradores de manera modular, aplicando diferentes aspectos de funcionalidad sin modificar la función original.
Los decoradores anidados y con parámetros en Python permiten aplicar múltiples transformaciones a funciones o métodos de una forma flexible y reutilizable. Aquí te explico cómo funcionan ambos conceptos y te muestro ejemplos. \### 1. Decoradores Anidados Los decoradores anidados son simplemente varios decoradores aplicados a una misma función, uno tras otro. Se aplican en el orden en que aparecen, de afuera hacia adentro. Esto significa que el decorador más cercano a la función será ejecutado primero. \*\*Ejemplo de decoradores anidados:\*\* ```python def decorador1(funcion): def wrapper(\*args, \*\*kwargs): print("Ejecutando decorador1") return funcion(\*args, \*\*kwargs) return wrapper def decorador2(funcion): def wrapper(\*args, \*\*kwargs): print("Ejecutando decorador2") return funcion(\*args, \*\*kwargs) return wrapper @decorador1 @decorador2 def saludo(nombre): print(f"Hola, {nombre}") saludo("Carlos") ``` \*\*Salida:\*\* ```plaintext Ejecutando decorador1 Ejecutando decorador2 Hola, Carlos ``` En este caso: \- `decorador2` se aplica primero, luego `decorador1`. \- `saludo` pasa por ambos decoradores antes de ejecutar su lógica. \### 2. Decoradores con Parámetros Los decoradores con parámetros permiten personalizar el comportamiento del decorador. Para crear un decorador con parámetros, se define una función que recibe estos parámetros y que, a su vez, devuelve el decorador propiamente dicho. \*\*Ejemplo de decorador con parámetros:\*\* ```python def repetir(n): def decorador(funcion): def wrapper(\*args, \*\*kwargs): for \_ in range(n): funcion(\*args, \*\*kwargs) return wrapper return decorador @repetir(3) def saludo(nombre): print(f"Hola, {nombre}") saludo("Carlos") ``` \*\*Salida:\*\* ```plaintext Hola, Carlos Hola, Carlos Hola, Carlos ``` Aquí: \- `repetir(3)` llama al decorador `repetir` con `n=3`. \- El decorador envuelve a `saludo`, que se ejecutará 3 veces. \### 3. Decoradores Anidados con Parámetros Podemos combinar ambas ideas aplicando varios decoradores con parámetros. Esto permite una gran flexibilidad y personalización en el comportamiento de las funciones decoradas. \*\*Ejemplo de decoradores anidados con parámetros:\*\* ```python def prefijo(texto): def decorador(funcion): def wrapper(\*args, \*\*kwargs): print(texto, end=" ") return funcion(\*args, \*\*kwargs) return wrapper return decorador def repetir(n): def decorador(funcion): def wrapper(\*args, \*\*kwargs): for \_ in range(n): funcion(\*args, \*\*kwargs) return wrapper return decorador @prefijo("Atención:") @repetir(2) def saludo(nombre): print(f"Hola, {nombre}") saludo("Carlos") ``` \*\*Salida:\*\* ```plaintext Atención: Hola, Carlos Atención: Hola, Carlos ``` En este ejemplo: \- `@repetir(2)` envuelve la función `saludo` para ejecutarse 2 veces. \- `@prefijo("Atención:")` envuelve `saludo` añadiendo el prefijo "Atención:" antes de cada saludo. \### Detalles Técnicos Cuando usas decoradores anidados con parámetros, el orden de ejecución sigue siendo de afuera hacia adentro. Esto permite aplicar las personalizaciones de los decoradores en el orden deseado, haciendo que cada paso dependa del resultado del anterior. Esta técnica es especialmente útil cuando necesitas funcionalidades como: \- \*\*Autorización y autenticación:\*\* Un decorador puede verificar permisos antes de que otro ejecute la lógica principal. \- \*\*Registro y monitoreo:\*\* Puedes aplicar un decorador que registre la ejecución de una función antes de realizar otras acciones. \- \*\*Manipulación de datos:\*\* Un decorador puede transformar datos de entrada o salida antes de que otro decorador aplique sus cambios.
```js class User: def __init__(self, name:str, role:str) -> None: self.name = name self.role = role def get_current_user(): return User('gb.so', 'admin') # función decoradora def check_access(required_role: str): #aquí recibimos el parámetro enviado al decorador def decorator(func): #este es el decorador que recibe la función def wrapper(user: User): # función envolvente, es necesario poner los parámetros current_user = get_current_user() if current_user.role == required_role: return func(user) else: raise Exception(f'el usuario {current_user.name} no tiene permitida la acción de eliminar usuarios porque no es {required_role}') return wrapper return decorator @check_access('admin') # decorador en uso def delete_user(user: User): print('usuario eliminado') user_to_delete = User('pepe.cierra', 'cliente') delete_user(user_to_delete) ```class User:    def \_\_init\_\_(self, name:str, role:str) -> None:        self.name = name        self.role = role def get\_current\_user():    return User('gb.so', 'admin') \# función decoradoradef check\_access(required\_role: str): #aquí recibimos el parámetro enviado al decorador    def decorator(func): #este es el decorador que recibe la función        def wrapper(user: User):  # función envolvente, es necesario poner los parámetros            current\_user = get\_current\_user()            if current\_user.role == required\_role:                return func(user)            else:                raise Exception(f'el usuario {current\_user.name} no tiene permitida la acción de eliminar usuarios porque no es {required\_role}')        return wrapper    return decorator @check\_access('admin')  # decorador en usodef delete\_user(user: User):    print('usuario eliminado') user\_to\_delete = User('pepe.cierra', 'cliente')delete\_user(user\_to\_delete)
Me es difícil entender por qué en el decorador de check\_access se están usando 3 funciones: la del decorador propiamente, la de decorator y la de wrapper, ya que en la clase pasada, se hizo un decorador con la misma funcionalidad pero solo definiendo 2 funciones: check\_access y wrapper.
Mi aporte![](https://static.platzi.com/media/user_upload/Captura%20de%20pantalla%202025-02-17%20a%20la%28s%29%2012.48.38p.m.-808c21ea-0f07-4c2d-b8cb-d925ca1c57f9.jpg)
Yo quise crear un archivo .txt que guardara los logs. Y así me quedó:  ```python import os # decorador que comprueba si un empleado tiene un rol específico def checkaccess(requiered_role): #param: str = 'admin' def decorator(func): #func: log_action def wrapper(employee): #dict: employee if employee.get('role') == requiered_role: return func(employee) # se rompe aquí else: print(f'you cannot erase this user. {employee.get("name")}') return wrapper return decorator def log_action(func): def wrapper(employee): if os.path.exists('log.txt'): with open('log.txt', 'a') as file: file.write(f'11/11/2001 - {func.__name__} created {employee} \n') else: # no sé si cuando no existe el archivo, el anterior if ya lo crea. explicame with open('log.txt', mode='w') as file: file.write(f'1/1/1999 log created. \n 11/11/2001 - {func.__name__} created {employee}\n') print(f'logging done') return func(employee) # llama a delete_e return wrapper """decoradores anidados: - El primero, tiene la información del decorador de adentro - Primero, crea el decorador de afuera y luego el de adentro """ @checkaccess('admin') @log_action def delete_e(employee): print(f'delete employee {employee.get("name")}') employee = {'name':'Juan', 'role':'admin'} delete_e(employee) # delete employee Juan `````` Funciona 10/10
```python print("") print("* Ejercicio 1:") print("- Uso de decoradores para verificar acceso y registrar eventos (con logs de inicio y fin).") print("") # Decorador que comprueba si un empleado tiene un rol específico. def verificar_acceso(requerido_rol): """ Decorador para verificar el acceso de un empleado según su rol. Este decorador crea otro decorador interno (`decorador`). Este último verifica si un empleado tiene un rol específico (`requerido_rol`) antes de permitir el acceso a la función decorada. Args: requerido_rol: El rol requerido para acceder a la función (str). Returns: La función `decorador`, que es otro decorador. """ def decorador(func): """ Decorador interno que realiza la verificación del rol. Args: func: La función que se va a decorar (la función a la que se quiere restringir el acceso). Returns: La función `envolvedor` (wrapper). """ def envolvedor(empleado): """ Función envoltorio (wrapper) que realiza la verificación y la llamada. Args: empleado: Un diccionario que representa la información del empleado. Returns: El resultado de llamar a `func` si el empleado tiene el rol requerido, o `None` en caso contrario. También imprime un mensaje de acceso denegado si el empleado no tiene el rol correcto. """ if empleado.get('rol').upper() == requerido_rol.upper(): # Modificación para ser insensible a mayúsculas resultado = func(empleado) return resultado else: print(f"Acceso denegado. Solo {requerido_rol} puede realizar esta acción") return None # Retorna None explícitamente return envolvedor return decorador def log_evento(func): """ Decorador para registrar eventos relacionados con un empleado. Este decorador envuelve una función y añade un mensaje de registro antes de su ejecución. Imprime un mensaje indicando el inicio de una transacción para un empleado. Args: func: La función que se va a decorar. Returns: La función `envolvedor` (wrapper). """ def envolvedor(empleado): print(f"Inicio evento para empleado {empleado.get('nombre')}...") resultado = func(empleado) # Captura el resultado de la función original print(f"Fin evento para empleado {empleado.get('nombre')}.") return resultado # Retorna el resultado de la funcion original return envolvedor @verificar_acceso('ADMIN') # Se usa el decorador externo. Modificado para ser insensible a mayusculas @log_evento # Se aplica el segundo decorador (el orden es importante) def eliminar_empleado(empleado): """ Función para eliminar un empleado (solo accesible para administradores). Args: empleado: Un diccionario con la información del empleado. Returns: Un mensaje indicando que el empleado fue eliminado """ return f"El empleado {empleado.get('nombre')} ha sido eliminado" usuario_admin = {"nombre": "Alexis Dorado", "rol": "ADMIN"} usuario_no_admin = {"nombre": "Juan Pérez", "rol": "EMPLEADO"} print("Prueba con usuario admin:") print(eliminar_empleado(usuario_admin)) print("\nPrueba con usuario no admin:") print(eliminar_empleado(usuario_no_admin)) ```
💖 Decoradores!
hola chicos estaba haciendo este ejercicio para una siguiente clase, pero estoy teniendo problemas con el decorador, si aguien puede detectar que estoy haciendo mal me serviria mucho ```js class NuAcount: def __init__(self,money,**owner): self.__money__=money self._owner_=owner def __update_money__(self,cuantity): if cuantity <0 and cuantity*-1> self.__money__: return ValueError('not enougth founds') else: self.__money__+=cuantity return 'succes' @property def money(self): return self.__money__; def __log__(self): def arguments(func): def wraper(*args): with open(f'transaccionsLog{self._owner_['name']}.txt','a')as log: result= func(*args) if result=='succes': log.write(f'una transaccion fue realizada el saldo actual es {self.money}') return result return wraper return arguments @__log__ def transaction (self,direction,quantity): if isinstance(direction,str)and isinstance(quantity,int|float): match direction: case 'send': if quantity>0: return self.__update_money__(quantity*-1) else: return self.__update_money__(quantity) case 'recive': if quantity>0: return self.__update_money__(quantity) else: return self.__update_money__(quantity*1) case _: print('do you want to send or recive the money?') if __name__=='__main__': owner={'name':'sutanito','id':'666','nacionality':'valhala'} cuenta=NuAcount(45,**owner) cuenta.transaction('recive',50) print(cuenta.money) ```
¿no entiendo que es eso de registrar la accion? copilot me dice que la funcion de log\_action es esa pero no entiendo eso que significa, realmente no entiendo porque log accion existe si el wrapper no le hace nada a la funcion.
Los decoradores en Python ofrecen ventajas sobre las funciones tradicionales al permitir la modificación y extensión del comportamiento de las funciones de manera más concisa y reutilizable. Con un decorador, puedes aplicar múltiples funcionalidades a una función sin modificar su código interno. Esto es especialmente útil para tareas como la validación de acceso, el registro de acciones o el manejo de excepciones. Además, los decoradores promueven un enfoque más limpio y modular, lo que facilita el mantenimiento y la legibilidad del código.