|
| 1 | +""" |
| 2 | + EJERCICIO: |
| 3 | + Explora el concepto de "decorador" y muestra cómo crearlo |
| 4 | + con un ejemplo genérico. |
| 5 | + DIFICULTAD EXTRA (opcional): |
| 6 | + Crea un decorador que sea capaz de contabilizar cuántas veces |
| 7 | + se ha llamado a una función y aplícalo a una función de tu elección. |
| 8 | +""" |
| 9 | + |
| 10 | +print(f"{'#' * 47}") |
| 11 | +print(f"## Explicación {'#' * 30}") |
| 12 | +print(f"{'#' * 47}") |
| 13 | + |
| 14 | +print(r""" |
| 15 | +Los decoradores son funciones que modifican el comportamiento de otras funciones. Pueden ser los que entrega Python por default (por ejemplo |
| 16 | +staticmethod y classmethod) o funciones creadas para determinada función. |
| 17 | +
|
| 18 | +Por ejemplo, creo una clase Turno para entregar turnos de una tienda con varios sectores. La clase Turno tendrá tres métodos decorados: |
| 19 | + 1- hora_de_emision decorado con "staticmethod" indicando que es de clase PERO no recive ni entrega argumentos de la clase. |
| 20 | + 2- localiza_sector decorado con "classmethod" indicanco que es de clase y entregando el contenido de una variable de la clase. |
| 21 | + 3- entrega_de_turno decorado con "classmethod" indicando que es de clase y modificando y entregando una variable de clase. |
| 22 | +
|
| 23 | +Luego tenemos el decorador "asesor" el cual se encarga de ejecutar comandos pre y post callback de la función decorada (va a dar instrucciones |
| 24 | +de localización, va a llamar a la función que muestra el turno y luego va a hacer un saludo final). |
| 25 | +
|
| 26 | +Los decoradores se invocan con un "@"<nombre_de_la_función_decoradora> justo antes de definir la función decorada. |
| 27 | +
|
| 28 | + def mi_decorador(callback_func): |
| 29 | + def wrapper(*args, **kwargs) |
| 30 | + <ejecuto PRE operaciones> |
| 31 | + callback_func(*args, **kwargs) |
| 32 | + <ejecuto POST operaciones> |
| 33 | + return wrapper |
| 34 | +
|
| 35 | + @mi_decorador |
| 36 | + def funcion_decorada(): |
| 37 | + ... |
| 38 | +
|
| 39 | +Ejemplo: |
| 40 | +
|
| 41 | +from time import sleep |
| 42 | +
|
| 43 | +
|
| 44 | +class Turno: |
| 45 | + turno: int = 1000 |
| 46 | + ubicacion = {"Farmacia": "por pasillo central al fondo", |
| 47 | + "Perfumería": "por escalera primer piso", |
| 48 | + "Gabinete": "por pasillo de la derecha"} |
| 49 | +
|
| 50 | + def __init__(self, sector): |
| 51 | + self.sector = sector |
| 52 | + self.hora = self.hora_de_emision() |
| 53 | + self.turno = Turno.entrega_turno() |
| 54 | +
|
| 55 | + @staticmethod |
| 56 | + def hora_de_emision(): |
| 57 | + from datetime import datetime |
| 58 | + return datetime.now().strftime('%H:%M:%S') |
| 59 | +
|
| 60 | + @classmethod |
| 61 | + def localiza_sector(cls, sector): |
| 62 | + return cls.ubicacion[sector] |
| 63 | +
|
| 64 | + @classmethod |
| 65 | + def entrega_turno(cls): |
| 66 | + cls.turno += 1 |
| 67 | + return cls.turno |
| 68 | +
|
| 69 | +
|
| 70 | +def asesor(funcion_decorada): |
| 71 | + def wrapper(*args, **kwargs): |
| 72 | + # *args, **kwargs son los argumentos de la función decorada "ver_turno: args[0] = nombre y args[1] L instancia del objeto Turno" |
| 73 | + print(f"{args[0]} dirijase {args[1].localiza_sector(args[1].sector)}") |
| 74 | + funcion_decorada(*args, **kwargs) |
| 75 | + print("Gracias por su visita.\n") |
| 76 | +
|
| 77 | + return wrapper |
| 78 | +
|
| 79 | +
|
| 80 | +@asesor |
| 81 | +def ver_turno(nombre, turno): |
| 82 | + print(f"Tiene el turno {turno.turno} de la hora {turno.hora} para {turno.sector}") |
| 83 | +
|
| 84 | +
|
| 85 | +nestor = Turno("Farmacia") |
| 86 | +sleep(1) |
| 87 | +neslarra = Turno("Farmacia") |
| 88 | +sleep(1) |
| 89 | +nesla = Turno("Perfumería") |
| 90 | +sleep(1) |
| 91 | +otro_nestor = Turno("Gabinete") |
| 92 | +
|
| 93 | +ver_turno("Néstor", nestor) |
| 94 | +ver_turno("Neslarra", neslarra) |
| 95 | +ver_turno("Nesla", nesla) |
| 96 | +ver_turno("Otro Néstor", otro_nestor) |
| 97 | +
|
| 98 | +Ésto devuelve: |
| 99 | +
|
| 100 | +Néstor dirijase por pasillo central al fondo # decorador PRE operación |
| 101 | +Tiene el turno 1001 de la hora 18:28:14 para Farmacia # función decorada |
| 102 | +Gracias por su visita. # decorador POST operación |
| 103 | +
|
| 104 | +Neslarra dirijase por pasillo central al fondo # decorador PRE operación |
| 105 | +Tiene el turno 1002 de la hora 18:28:15 para Farmacia # función decorada |
| 106 | +Gracias por su visita. # decorador POST operación |
| 107 | +
|
| 108 | +Nesla dirijase por escalera primer piso # decorador PRE operación |
| 109 | +Tiene el turno 1003 de la hora 18:28:16 para Perfumería # función decorada |
| 110 | +Gracias por su visita. # decorador POST operación |
| 111 | +
|
| 112 | +Otro Néstor dirijase por pasillo de la derecha # decorador PRE operación |
| 113 | +Tiene el turno 1004 de la hora 18:28:17 para Gabinete # función decorada |
| 114 | +Gracias por su visita. # decorador POST operación |
| 115 | +""") |
| 116 | + |
| 117 | +print(f"{'#' * 52}") |
| 118 | +print(f"## Dificultad Extra {'#' * 30}") |
| 119 | +print(f"{'#' * 52}\n") |
| 120 | + |
| 121 | +def contador_de_ejecuciones(funcion): |
| 122 | + ejecuciones = {} |
| 123 | + def wrapper(*args, **kwargs): |
| 124 | + ejecuciones[funcion.__name__] = ejecuciones[funcion.__name__] if funcion.__name__ in ejecuciones.keys() else 0 |
| 125 | + print(f"Ejecutando {funcion.__name__}", end="\n\t") |
| 126 | + funcion(*args) |
| 127 | + ejecuciones[funcion.__name__] += 1 |
| 128 | + print(f"{funcion.__name__} se ha ejecutado {ejecuciones[funcion.__name__]} veces.\n") |
| 129 | + return wrapper |
| 130 | + |
| 131 | + |
| 132 | +@contador_de_ejecuciones |
| 133 | +def saludo_espaniol(nombre): |
| 134 | + print(f"{nombre} Hola Mundo") |
| 135 | + |
| 136 | + |
| 137 | +@contador_de_ejecuciones |
| 138 | +def saludo_ingles(nombre): |
| 139 | + |
| 140 | + print(f"{nombre} Hello World") |
| 141 | +@contador_de_ejecuciones |
| 142 | +def saludo_frances(nombre): |
| 143 | + print(f"{nombre} Alo Monde") |
| 144 | + |
| 145 | +@contador_de_ejecuciones |
| 146 | +def saludo_italiano(nombre): |
| 147 | + print(f"{nombre} Ciao Mondo") |
| 148 | + |
| 149 | + |
| 150 | +saludo_ingles("Pete") |
| 151 | +saludo_italiano("Peppo") |
| 152 | +saludo_ingles("Joe") |
| 153 | +saludo_ingles("Jhonny") |
| 154 | +saludo_espaniol("Tonio") |
| 155 | +saludo_espaniol("Pepe") |
| 156 | +saludo_italiano("Gianni") |
| 157 | +saludo_frances("Peppete") |
| 158 | +saludo_frances("Jean") |
| 159 | +saludo_italiano("Carletto") |
0 commit comments