Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Curso Profesional de Python

Curso Profesional de Python

Facundo García Martoni

Facundo García Martoni

Programando decoradores

11/21
Recursos

Aportes 239

Preguntas 15

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

Seguramente también han visto decoradores que reciben parámetros, para esto solo tiene que anidar una función más para que esta reciban los parámetros del decorador y la siguiente es la que recibe la función a la que decora.

Este es el código, solo funciona con texto, no hice lo de *args.

Y este sería el resultado XD

Acá el mío jejeje


Hola compañeros esta es mi aplicación de decoradores, pues sucede que soy Data Scientist y estoy entrenando un modelo de IA que es capaz de generar texto, y actualmente funciona como un chatbot, pero aun no esta perfecto y comete ciertos erres y a veces dice palabras que no quiero xdxd … entonces debo hacer una limpieza y formatear el texto una vez terminada la predicción:

entonces la lógica para hacer la limpieza la cree dentro de un decorador:

y luego lo importo el decorador para utilizarlo al momento de generar texto:

y ahora le cuento a Kate que estoy aprendiendo decoradores con Facundo(Kate se llama mi modelo) 😃

Yo realice el juego de piedra, papel o Tijera, donde la maquina selecciona su jugada de manera random y nosotros utilizamos la función mi_turno para pasarle la jugada desde una variable global. Y la función wrapper se encarga de analizar quien gana.

Al ejecutar:

Hice un decorador para poner en memoria cache consultas de SQL para evitar conexiones hacia la base de datos

Hola, aquí mi reto que decidí hacer. Básicamente lo que hace es obtener la distancia euclidiana entre dos puntos, que es la que todos conocen. Pero aparte la decore con una función para obtener la distancia de manhattan.


Agregué un decorador a mi juego del ahorcado donde ahora muestra lo que demoro en ganar el juego, lo mas sorprendente es que me funcionó jaja 😀

Hice que el mío tomara una función que lee un archivo csv, y me devuelva una pequeña descripción de los datos leídos.

def describe_df(func):
    def wrapper():
        func()
        print(f'El tamano del data set es: {func().shape}')
        print(f'Los tipos de datos del dataset son:\n{func().dtypes}')

    return wrapper


@describe_df
def data_csv():
    df = pd.read_csv('Direccion archivo csv')
    return df

Reto Libre

El siguiente programa consiste en encriptar un texto por medio del cifrado César, que consiste en correr la posición de los caracteres que componen el texto a través del alfabeto o un listado alfanumérico.

La función encrypt cifra el texto mediante el número de posiciones a correr, estos son datos ingresados por el usuario (text, shift_number).

El decorador entrega una función que permite descifrar el texto.

def decrypt(func):
    def wrapper(text: str, shift_number: int) -> str:
        shift_number = shift_number * (-1)
        return func(text, shift_number)
    return wrapper

def encrypt(string: str, shift_number: int) -> str:
    alphabet_lower = "abcdefghijklmnñopqrstuvwxyz"
    alphabet_upper = "ABCDEFGHIJKLMNÑOPQRSTUVWXYZ"
    numbers = "0123456789"

    encrypted = ""  # Encrypted string

    for charact in string:
        if charact.islower() and (charact in alphabet_lower):
            index = alphabet_lower.find(charact)
            index = (index + shift_number) % 27
            encrypted += alphabet_lower[index]
        elif charact.isupper() and (charact in alphabet_upper):
            index = alphabet_upper.find(charact)
            index = (index + shift_number) % 27
            encrypted += alphabet_upper[index]
        elif charact in numbers:
            index = numbers.find(charact)
            index = (index + shift_number) % 10
            encrypted += numbers[index]
        else:
            encrypted += charact # for special characters
    
    return encrypted

if __name__ == "__main__":
    text = input("Enter the text to encrypt: ")
    shifts_number = int(input("Enter the number of shifts: "))
    encrypted_text = encrypt(text, shifts_number)
    print("\n Encrypted text: " + encrypted_text)

    # Decrypt process
    decrypt_function = decrypt(encrypt)
    decrypt_text = decrypt_function(encrypted_text, shifts_number)
    print("\n Decrypted text: " + decrypt_text)

Muy interesante y divertido!

Realicé un pequeño programa al que podemos ingresarle el hábito que queremos desarrollar y la cantidad de minutos al día que le vamos a dedicar, aplicando lo que aprendimos de decoradores y closures. cuentenmé qué tal les parece y qué puedo mejorarle. 😁

def year_of_daily_effort(func):
    def wrapper(*args, **kwargs):
        func(*args, **kwargs)
        habit_and_time = args
        total_yearly = int(habit_and_time[1])*365
        print('At the end of the year you will practice ' + str(habit_and_time[0])+' a total of '+str(total_yearly)+' minutes!')
    return wrapper

@year_of_daily_effort
def daily_habit(habit: str, minutes: int) -> str: 
    print(f"your habit is {habit} for {minutes} minutes daily")
    
daily_habit("yoga",25)

#OUTPUT
#your habit is yoga for 25 minutes daily
#At the end of the year you will practice yoga a total of 9125 minutes! 

Como pueden notar, descubrí que podemos hacer operaciones conlor args dentro del wrapper accediendo a ellos como componentes de una lista según fueron ingresados.

😆 Yo hice un decorador que contara las palabras más comunes de una canción. 🎶🎶🎶
👉 Repositorio Completo

import urllib.request
from collections import Counter


def word_counter(func):
    def counter(*args, **kwargs):
        data = func(*args, **kwargs)    
        total_words = data.split()
        stopwords = ['y','Y','la','de','una','los','me','No','con','que','el','un','es','en','Que','muy','al','a','él','le','quiere','A','da','faltan','Mas','bien']
        words = [word for word in total_words if word not in stopwords]
        wordcount = Counter(words)
        print('\n>>> TOP FIVE WORDS IN THIS SONG <<<\n')
        for w in wordcount.most_common(5):
            print(f"{w[0]}: {w[1]}")
    return counter


@word_counter
def text_reader(url):  
    data = urllib.request.urlopen(url).read().decode('utf_8') 
    return data



chilanga_banda = 'https://raw.githubusercontent.com/isabelyb/word_counter/main/chilanga_banda_lyrics.txt'
p_to = 'https://raw.githubusercontent.com/isabelyb/word_counter/main/pto.txt'
ciclon = 'https://raw.githubusercontent.com/isabelyb/word_counter/main/ciclon.txt'

# Output

text_reader(chilanga_banda)
# >>> TOP FIVE WORDS IN THIS SONG <<<
# bailan: 8
# tibiritábara: 8
# Pachucos: 4
# cholos: 4
# chundos: 4

text_reader(p_to)
# >>> TOP FIVE WORDS IN THIS SONG <<<
# Puto,: 26
# machino: 8
# Marica: 4
# nena: 4
# putino: 4

text_reader(ciclon)
# >>> TOP FIVE WORDS IN THIS SONG <<<
# rueda: 8
# vueltas: 7
# flecha: 6
# Gira: 6
# Dios: 3

Cowsay con Decoradores - Reto de la Clase:

Hice la vaquita que vimos en el curso de terminal, permite poner el texto que deseemos, siempre que sea de una línea para que lo diga la vaquita cow, espero les guste (y sirva de guía para lo que podemos hacer con decoradores):

# Decorador para usar Cowsay con cualquier texto (a 1 línea)

from datetime import date, datetime

def cowsay(func):
    def wrapper(text):
        lenght = len(text)
        print(" _" + lenght*"_" + "_ ")
        print("< " + text + " > ")
        print(" -" + lenght*"-" + "- ")
        print("        \   ^__^ ")
        print("         \  (oo)\_______ ")
        print("            (__)\       )\/\ ")
        print("                ||----w | ")
        print("                ||     || ")
    return wrapper

@cowsay
def mytext(text):
        print(text)

mytext("No pares de aprender!")

Buenas comparto mi código, hice un decorador que te devuelve el nombre de la función que ingresas en formato ASCII artístico para ello debes instalar pyfiglet con pip install pyfiglet.
Codigo:

import pyfiglet

def print_name(func):
    def wrapper():
        name = func.__name__
        ascii_banner = pyfiglet.figlet_format(name)
        print(ascii_banner)
        func()
    return wrapper

@print_name
def Platzi():
    print("Running function...")

Platzi()

Resultado:

este es el mío, sencillo pero funciona

import os

def decorator(func):
    def wrapper():
        os.system('cls')
        print('❤❤❤                                                     ⭐⭐⭐')
        func()

    return wrapper    


@decorator
def gereetings():
    greeting = input('intruduce tu nombre: ')
    print('hola un gusto conocerte', greeting.capitalize(), 'nos alegra mucho conocerte')


def run():
    gereetings()


if __name__=='__main__':
    run()

Haciendo un web scraper a https://news.ycombinator.com/ , tome el título y el link de cada artículo y al final usando un decorador coloque un emoji que se escoge aleatoriamente.


import requests
import lxml.html as html
import datetime
import emoji
import random

HOME_URL = 'https://news.ycombinator.com/'
XPATH_LINK_TO_ARTICLE = '//td[@class="title"]/a/@href'
XPATH_TITLE = '//td[@class="title"]/a/text()'


def random_emoji():
  list_emojis = ["💚","🐍","🚀","🐱‍👤","🏛","🗺","🤣","👌","🐱‍🐉", "🐲", "🐘", "🦘", "🐳", "🧠", "🦾", "💅", "🎈", "📗", "🟨"]
  rand = random.choice(list_emojis)
  return rand

def put_emoji(parse_home):
  def wrapper(*args, **kwargs):
    parse_home()
    today = datetime.date.today().strftime('%d-%m-%Y')
    with open(f'{today}.txt', 'a', encoding='utf-8') as f:
        f.write(f'\n\t\tThe emoji of today is: {args[0]}\n')
  return wrapper

@put_emoji
def parse_home():
  try:
    response = requests.get(HOME_URL)
    if response.status_code ==200:
      home = response.content.decode("utf-8")
      parsed = html.fromstring(home)
      links_to_articles = parsed.xpath(XPATH_LINK_TO_ARTICLE)
      title_of_articles = parsed.xpath(XPATH_TITLE)
      today = datetime.date.today().strftime('%d-%m-%Y')

      with open(f'{today}.txt', 'w', encoding='utf-8') as f:
        for i in range(0,len(title_of_articles)-1):
          f.write(f'Title description: {title_of_articles[i]}')
          f.write(f'\n\t Link: {links_to_articles[i]}')
          f.write('\n\n')
    else: 
      raise ValueError(f"Error: {response.status_code}")
  except ValueError as ve:
    print(ve)

def run():
  rand=random_emoji()
  parse_home(rand)

if __name__ == '__main__':
  run()

Sign up para un Viaje Interestelar

Hola Amigos, el programa que hice está basado en un tipo Sign Up sencillo, para saber si una persona o tripulante puede hacer un Viaje Interestellar! 😄
Los parámetros para evaluar al viajero fueron tomados de los requisitos que pide la NASA para ser un astronauta.



Code

El código puede ser partido y repartido en muchos módulos (packages), por cuestiones de practicidad

  • Posdata: Sí, el código estará subido en un repositoriod de GitHub, lo encontrarás en los tutoriales de este curso, al final del mismo!
from platform import system
from os import system as console_command
from time import sleep
from datetime import date
from typing import Any, Callable, Generator, List
from numpy import arange as np_range


# Validations

def validate_strings(x: int, y: int, header: str, error_message: str) -> str:
  """Validate strings."""

  while True:
    gotoxy(x, y); print(header, end='')
    gotoxy(x+len(header), y); string_not_formatted: str = input('').rstrip().title()
    if string_not_formatted.replace(' ', '').isalpha() and string_not_formatted != '':
      if string_not_formatted[0] != ' ':
        blank_space: List = [pos for pos, char in enumerate(string_not_formatted) if char == ' ']
        into_bucle: bool = False
        for idx in blank_space:
          try:
            iterator: int = idx + 1
            if string_not_formatted[idx] == string_not_formatted[iterator]:  # ' ' == ' ' -> ERROR!
              into_bucle = True
              break
          except IndexError: pass
        if not into_bucle:
          string: str = ''
          for letter in string_not_formatted.split(): string += letter + ' '
          return string.strip()
      else: pass
    else: pass
    gotoxy(x+len(header)+len(string_not_formatted), y); print(error_message)
    sleep_screen(x+len(header)+len(string_not_formatted), y, error_message, string_not_formatted)

def validate_floats(x: int, y: int, header: str, error_message: str, type: str) -> float:
  """Validate floats."""

  while True:
    gotoxy(x, y); print(header, end='')
    try:
      gotoxy(x+len(header), y); numbers: str = input('').rstrip()
      if numbers[0] != ' ':
        if type == 'w':
          number_weight = [round(x, 2) for x in np_range(20, 635.01, 0.01)]
          if binary_search(number_weight, float(numbers)):
            return float(numbers)
        else:
          number_height = [round(i, 2) for i in np_range(0.72, 2.73, 0.01)]
          if binary_search(number_height, float(numbers)):
            return float(numbers)
      else: pass
    except ValueError: pass
    gotoxy(x+len(header)+len(numbers), y); print(error_message)
    sleep_screen(x+len(header)+len(numbers), y, error_message, numbers)

def validate_dates(x: int, y: int, header: str, error_message: str) -> date:
  """Validate dates."""
  
  while True:
    gotoxy(x, y); print(header, end='')
    try:
      gotoxy(x+len(header), y)
      string: str = input('').rstrip().replace(' ', '!').replace('\t', '!!!!!!!!')
      list_string: List = string.split('/')
      if list_string[0][0] != '0' and list_string[1][0] != '0' and list_string[2][0] != '0':
        if len(list_string) == 3:
          return date(int(list_string[0]), int(list_string[1]), int(list_string[2]))
        else: pass
      else: pass
    except (SyntaxError, ValueError, NameError, TypeError, IndexError): pass
    gotoxy(x+len(header)+len(string), y); print(error_message)
    sleep_screen(x+len(header)+len(string), y, error_message, string)

def calculate_age(birth_date: date) -> int:
  """Calculate age."""

  today: date = date.today()
  age: int = today.year - birth_date.year - ((today.month, today.day) < (birth_date.month, birth_date.day))
  return age

def validate_blood(x: int, y: int, header: str, error_message: str) -> str:
  """Validate type of blood."""
  
  while True:
    gotoxy(x, y); print(header, end='')
    gotoxy(x+len(header), y); string: str = input('').rstrip().upper()
    if string[0] != ' ':
      if len(string) in range(2, 4):
        if len(string) == 2:
          if string in ('O+', 'O-', 'A+', 'A-', 'B+', 'B-'): return string
          else: pass
        else:
          if string in ('AB+', 'AB-'): return string
          else: pass
    else: pass
    gotoxy(x+len(header)+len(string), y); print(error_message)
    sleep_screen(x+len(header)+len(string), y, error_message, string)
  
def validate_gender(x: int, y: int, header: str, error_message: str) -> str:
  """Validate a person's gender."""

  while True:
    string: str = validate_strings(x, y, header, error_message)
    if string[0] != ' ':
      if len(string) == 1:
        if string in ('M', 'F'): return string
        else: pass
    else: pass
    gotoxy(x+len(header)+len(string), y); print(error_message)
    sleep_screen(x+len(header)+len(string), y, error_message, string)


# Fuctions for the program.

def welcome_traveler() -> None:
  """Welcome the traveler and explain the program."""

  clean_screen()
  gotoxy(4, 4); print("INTERSTELLAR TRAVEL    ⊂(◉‿◉)つ")
  gotoxy(6, 6); print("* Hello traveler, welcome to the adventure of your life!")
  gotoxy(7, 8); print("+ Then, sign out to see if you can do interestellar")
  gotoxy(9, 9); print("travel without any problems.")
  gotoxy(6, 11); print("→ Press a key to continue..."); input('')

def greeting_traveler(func) -> Callable[[Any], Any]:
  """Greet the traveler."""

  def wrapper(*args: Any) -> Any:
    clean_screen()
    gotoxy(4, 4); print("INTERSTELLAR TRAVEL    ⊂(◉‿◉)つ")
    gotoxy(6, 6); print("→ Hello traveler, we are preparing")
    gotoxy(9, 7); print("you for the trip!")
    return func(*args)
  return wrapper

def processing(x: int, y: int, sms: str) -> None:
  """It's responsible for simulating a system processing."""

  for _ in range(1, 16):  # 5 seconds for processing.
    try:
      gotoxy(x, y); print(sms+next(generator))
      sleep(0.333333334)
      gotoxy(x, y); print('     '*len(sms))
    except (NameError, StopIteration):
      generator: Generator = (i for i in ('.  )', '.. )', '...)'))

@greeting_traveler
def choice_of_traveler(*args: Any) -> bool:
  """Initialize the traveler's choice."""

  args = args[0]
  age: int; height: float; bmi: float
  age, height, bmi = \
  args[0], args[1], args[2]
  traveler: List = []
  gotoxy(8, 9); print("» Validating data to know if you are")
  gotoxy(11, 10); print("an ideal candidate to travel.")
  # Test 1.
  sms_proc = "(Processing"
  gotoxy(8, 12); print("~ Age         (23-37)")
  processing(30, 12, sms_proc)
  if age in range(23, 38):
    gotoxy(30, 12); print('[ ✓ ]')
    traveler.append(True)
  else:
    gotoxy(30, 12); print('[ X ]')
    traveler.append(False)
  # Test 2.
  gotoxy(8, 13); print("~ Height  (1.50-1.90)")
  processing(30, 13, sms_proc)
  number_height = [round(i, 2) for i in np_range(1.50, 1.91, 0.01)]
  if binary_search(number_height, height):
    gotoxy(30, 13); print('[ ✓ ]')
    traveler.append(True)
  else:
    gotoxy(30, 13); print('[ X ]')
    traveler.append(False)
  # Test 3.
  gotoxy(8, 14); print("~ BMI (             )")
  processing(30, 14, sms_proc)
  if bmi < 18.5:
    gotoxy(15, 14); print(' Underweight ')
    gotoxy(30, 14); print('[ X ]')
    traveler.append(False)
  elif bmi >= 18.5 and bmi < 25:
    gotoxy(15, 14); print('Normal weight')
    gotoxy(30, 14); print('[ ✓ ]')
    traveler.append(True)
  elif bmi >= 25 and bmi < 30:
    gotoxy(15, 14); print(' Overweight  ')
    gotoxy(30, 14); print('[ X ]')
    traveler.append(False)
  elif bmi >= 30:
    gotoxy(15, 14); print('   Obesity   ')
    gotoxy(30, 14); print('[ X ]')
    traveler.append(False)
  if False in traveler: return False
  else: return True

def goodbyes(name: str, choice: bool) -> None:
  """Farewell to the traveler and tells him
  if he passed the test to make the trip or not."""

  if choice:
    gotoxy(6, 16); print("→ Congratulations {}! You are an ideal candidate.".format(name))
  else:
    gotoxy(6, 16); print("→ Sorry {}, you are not an ideal candidate.".format(name))
  gotoxy(0, 17); print('')
  gotoxy(8, 18); print("→ Press a key to exit..."); input('')


# Utilities

def calculate_bmi(weight: float, height: float) -> float:
  """Calculate the Body Mass Index."""

  return round(weight / (height**2), 1)

def binary_search(list_num: List, item: float) -> Any:
  """Binary search algorithm."""

  if len(list_num) == 0: return False
  else:
    midpoint = len(list_num) // 2
    if list_num[midpoint] == item: return True
    else:
      if item < list_num[midpoint]: return binary_search(list_num[:midpoint], item)
      else: return binary_search(list_num[midpoint+1:], item)

def gotoxy(x: int, y: int) -> None:
  """This function is in charge of positioning
     the cursor on any axis of the console."""

  print ("%c[%d;%df" % (0x1B, y, x), end='')

def clean_screen() -> None:
  """This function is responsible for cleaning the screen."""

  if system() == 'Windows': console_command('cls')
  else: console_command('clear')

def sleep_screen(x: int=4, y: int=20, error: str='',
                 date_input: Any='', time: int=3) -> None:
  """This function is responsible for cleaning the
     screen while waiting a few seconds."""

  for second in reversed(range(1, time+1)):
    gotoxy(x+len(error), y); print(' '*150)
    if second != 1:
      gotoxy(x+len(error), y); print("  //  Wait", second, "seconds!")
      sleep(1)
    else:
      gotoxy(x+len(error), y); print("  //  Wait", second, "second !")
      sleep(1)
  gotoxy(x-len(date_input), y); print(' '*200)


# Main program.

def main():
  ERROR_MESSAGE = "    Please enter a valid information..."
  welcome_traveler()
  clean_screen()
  gotoxy(4, 4); print("INTERSTELLAR TRAVEL    ⊂(◉‿◉)つ")
  gotoxy(10, 6); print("TRAVELER DATA")
  names_tvl:      str =  validate_strings(10, 8, "→  Names                      : ", ERROR_MESSAGE)
  birthday_tvl:  date =    validate_dates(10, 9, "→  Birthday  (year/month/day) : ", ERROR_MESSAGE)
  age_tvl:        int =     calculate_age(birthday_tvl)
  gotoxy(10, 10);                          print("→  Age                        :", str(age_tvl), 'years old')
  gender_tvl:     str =  validate_gender(10, 11, '→  Gender (Male"M"|Female"F") : ', ERROR_MESSAGE)
  blood_type_tvl: str =   validate_blood(10, 12, "→  Blood Type   (O+, A-...N±) : ", ERROR_MESSAGE)
  height_tvl:   float =  validate_floats(10, 13, "→  Height            (Meters) : ", ERROR_MESSAGE, 'h')
  weight_tvl:   float =  validate_floats(10, 14, "→  Weight         (Kilograms) : ", ERROR_MESSAGE, 'w')
  gotoxy(6, 16);                           print("→ Press a key to continue..."); input('')
  bmi_tvl:      float = calculate_bmi(weight_tvl, height_tvl)
  choice_tvl:    bool = choice_of_traveler((age_tvl, height_tvl, bmi_tvl))
  goodbyes(names_tvl, choice_tvl)
  clean_screen()


if __name__ == '__main__':
  main()

*ARGS y **KWARGS
Para mayor desarrollo de ambos conceptos, les dejo las siguientes lecturas:

concepto: https://www.geeksforgeeks.org/args-kwargs-python/

10 Examples to Master *args and **kwargs in Python: https://towardsdatascience.com/10-examples-to-master-args-and-kwargs-in-python-6f1e8cc30749

Creo que se entiende además de ser divertido 😄

Decorador para pasar a minúsculas:

Output:

Hice mi propio decorador que indica cual es la dificultad de una función a traves de la cantidad de argumentos pasados (Espero que se entienda xd)

def function_level(func):
    def wrapper(*args, **kwargs):
        print(func(*args, **kwargs))
        n_lenghts = len(args)
        if n_lenghts == 1:
            print('It\'s an easy function')
        elif n_lenghts == 2 or n_lenghts == 3:
            print('It\'s a middle level function')
        else:
            print('It\'s a hard function')
    return wrapper        


@function_level
def division(a: int, b: int) -> int:
    return a/b
    

division(2, 2)

Reto
Bart say

def bart_say(func):
    def wrapper(text):
        func(text)
        print('   |/')
        print("|\/\/\/|")  
        print("|      |")
        print("|      |")
        print("| (o)(o)")
        print("C      _)")
        print("| ,___|")
        print("|   /")
        print("/____|")
        print("/     |")
    return wrapper

@bart_say
def print_text(input_text):
    text_len = len(input_text)
    print("⌈" + text_len * "¯" + "⌉")
    print("⁞" + input_text + "⁞")
    print("⌊" + text_len * "_" + "⌋")

def run():
    input_text = str(input("Input a text: "))
    print_text(input_text)

if __name__ == '__main__':
    run() 

Vamos a hacer un programa que nos diga si Thanos de mata o no cuando chasquea los dedos.

import random

def infinityGauntlet(func):
    def wrapper(*args, **kwargs):
        func(*args, **kwargs)
        fingerSnap=random.randint(0, 1)
        if fingerSnap == 1:
            print('Mueres')
        else:
            print('Vives')
    return wrapper

@infinityGauntlet
def genocide(name = 'Joel'):
    print('Hola '+ name + (', Thanos decide que: '))
    
genocide()

#Resultado:
#Hola Joel, Thanos decide que
#Vives

Codigo del reto:
Si tengo una funcion que reciba texto y quiero asegurarme que solo tencha letras
el decorador retorna el texto pero quitando caracteres que sean digitos

def num_extractor(func: callable) -> callable:
    def wrapper(text: str) -> str:
        nums_extracted = [char for char in text if not char.isdigit()]
        return "".join(nums_extracted)
    return wrapper


@num_extractor
def text_receiver(text: str) -> str:
    return text


text = "hola2 aksm22"
result = text_receiver(text)
print(result)  # hola aksm

Hice esto intentando aplicar los conocimientos de la trilogía de Python. Sacando la idea del curso de programación básica , calculando el peso en cada planeta.
Alguna mejora o mejor implementación me gustaría saberla:

PLANETS_GRAVITY = [
    {
        'value': 0,
        'name': 'Tierra',
        'grivity': 9.807
    },
    {
        'value': 1,
        'name': 'Marte',
        'grivity': 3.711
    },
    {
        'value': 2,
        'name': 'Jupiter',
        'grivity': 24.8
    },
    {
        'value': 3,
        'name': 'Mercurio',
        'grivity': 3.7,
    },
    {
        'value': 4,
        'name': 'Urano',
        'grivity': 8.89,
    },
    {
        'value': 5,
        'name': 'Venus',
        'grivity': 8.89,
    },
    {
        'value': 6,
        'name': 'Saturno',
        'grivity': 10.44,
    },
    {
        'value': 7,
        'name': 'Neptuno',
        'grivity': 11.15
    },
]

from datetime import datetime

def execution_time(calculate):       #Calcula el tiempo que se demora una funcion en ejecutarse
    def wrapper(*args, **kwargs):   #*arg, **kwargs SIRVE PARA PONER LOS ARGUMENTOS IMPISITAMENTE
        initial_time = datetime.now()   #imarca tiempo de inicializacion 
        calculate(*args, **kwargs)           #Ejecuta la funcio
        final_time = datetime.now()     #Marca tiempo de finalizacion
        time_elapsed = final_time - initial_time #Tiempo total = tiempo final - timpoInicial
        print('\nEl programa funciono por ' + str(round(time_elapsed.total_seconds(),2)) + ' segundos')
    return wrapper


def calculate(weight, planet):
    planet_name = [num_planet['name'] for num_planet in PLANETS_GRAVITY if num_planet['value'] == planet]
    planet_gravity = [num_planet['grivity'] for num_planet in PLANETS_GRAVITY if num_planet['value'] == planet]
    gravity_eart = [num_planet['grivity'] for num_planet in PLANETS_GRAVITY if num_planet['value'] == 0]

    my_weight_in_planet = weight * planet_gravity[0] / gravity_eart[0]

    print('\nTu peso en ', planet_name[0], 'es de ', str(round(my_weight_in_planet,2)),'kg')


@execution_time
def run():
    print('Tu peso en otros planetas')
    weight = int(input('¿Cuanto pesas?: kg '))
    planet = int(input('''¿De que planeta quiere saber tu peso?:
    1: Marte.
    2: Jupiter.
    3: Mercurio.
    4: Urano.
    5: Venus.
    6: Saturno.
    7: Neptuno.
    
    Ingresa el numero correspondiente: '''))

    while planet < 0 or planet > 7:
        planet = int(input('''Seleccion invalida 
        ¿De que planeta quiere saber tu peso'''))
        
    calculate(weight, planet)


if __name__ == '__main__':
    run()

Pequeño codigo que crea un archivo .txt con un mensaje dado:

Este es mi reto. En una lista creo un conjunto de materias y los créditos necesarios para aprobar esa materia. Luego desde la terminal pide el ingreso de la materia y los créditos obtenidos.

def verify_status_materia(func):
  def wrapper(materia, creditos):
    func(materia, creditos)
    assert type(materia) == str, "El nombre de la materia debe ser un string"
    assert type(creditos) == int, "El valor de los créditos debe ser un número"
    list_materias = [
      {
        "materia": "Geometria",
        "creditos": 18
      },
      {
        "materia": "Yoga",
        "creditos": 17
      },
      {
        "materia": "Desarrollo Web",
        "creditos": 17
      },
      {
        "materia": "Estructura de datos",
        "creditos": 15
      },
      {
        "materia": "Artes",
        "creditos": 16
      },
    ]

    res = list(filter( lambda datos: datos['materia'].lower() == materia.lower(), list_materias ))
    if (len(res) > 0):
      if creditos >= res[0]['creditos']:
        print("Felicidades, aprobaste!! :) ")
      else:
        print("Lo sentimos, acabas de reprobar la materia! :( ")  
    else:
      print("Materia no encontrada, digite correctamente la materia")    
        
  return wrapper

@verify_status_materia
def verificar_aprobacion(materia: str, nota: float):
  print("Bucando en la bd, por favor espere")
  for _ in range(1,50000000):
    pass


def run():
  materia = input("Ingresa el nombre de una materia: ")
  creditos = int(input("Ingresa los créditos obtenidios: "))
  verificar_aprobacion(materia, creditos)

if __name__ == '__main__':
  run()
    

![](

Hice este programita que te saca la media de una lista generada aleatoriamente(del 1 al 100), te dice cuanto se demora en ejecutar el proceso(incluido el tiempo que te toma escribir las variables).

También te lo grafica(En este punto no se si lo hice bien, ya que use la media de X y la media de Y para graficar , ojala alguien me pueda explicar.).

Independientemente de la funcionalidad me sirvió para recordar algunas cosas de otros cursos.

import random
from typing import List
from bokeh.plotting import figure, show
from estadistica import media
from datetime import datetime

def time_func(func) -> int:
    def lapse(*args, **kwargs):
        init_time = datetime.now()
        func(*args, **kwargs)
        end_time = datetime.now()
        total_time = end_time - init_time
        print("Se demora: " + str(total_time.total_seconds()))

    return lapse


def average(func) -> int:
    def average_print(*args):
        result_med = media(func(*args))

        return result_med

    return average_print


@average
def x_y_generator(list_size) -> List:
    list = []
    for _ in range(list_size):
        list.append(random.randrange(1, 100))

    return list


def show_figure(x_list, y_list):
    print(x_list, " Media de X")
    print( y_list, " Media de Y")
    graph = figure(title = "Bokeh Vertical Bar Graph") 
    width = 0.1
    graph.vbar(x_list, top = y_list, width = width) 
    show(graph) 


def generator_list(number_of_points, list_size):
    x_list: List [int] = []
    y_list: List [int] = []
    for _ in range(number_of_points):
        x_list.append(x_y_generator(list_size))
        y_list.append(x_y_generator(list_size))
    show_figure(x_list, y_list)

@time_func
def main():
    number_of_points = int(input("Cuantos puntos en tu grafico quieres?: "))
    list_size = int(input("Cuantos valores quieres por cada lista?: "))
    generator_list(number_of_points, list_size)
    
if __name__ =='__main__':
    main()

No es mucho, pero es trabajo honesto

En mi opinion si seria necesario los quiz cuando se termine un modulo…y a los mismos aumentar por lo menos a 6 preguntas…

Aquí dejo mi aporte, es un “jueguito” donde pierdes si te sale el fantasma.

import random
from os import system

door = """

------>  🚪  <------
Encontraste una puerta"""

decision = """
¿Quieres entrar?(y/n): """

decision_2 = """

Tienes un arma de los caza fantasma.
¿Quieres usarla?(y/n): """
pasos = """


-----------------------------------
👟  👟  👟  👟  👟.....caminando"""
nothing = """

En esta habitación no hay nada."""
boo = """
._ _ _ _ _ _ _ _
|                     |
|   BOOOO!    |
|_ _ _ _ _   _ _|
          \/
           👻"""


def walk_to(func):

    def steps():
        stuff = ['nada', 'nada', 'ghost']

        while True:
            behind_to = random.choice(stuff)

            print(pasos)
            
            print(door)
            deci = input(decision)

            if deci == 'y':

                if behind_to == 'nada':
                    system('clear')
                    print(nothing)
                elif behind_to == 'ghost':
                    func()
                    break
            
    return steps



def run():

    @walk_to
    def scare():
        system('clear')
        print(boo)
        print('Salado ñaño, PERDISTE')
    
    scare()



if __name__=='__main__':
    run() 

Espero que me puedan ayudar con consejos para poder seguir mejorando.
Nunca paren de aprender!

Un decorador para sacar la raíz cuadrada.

def square_root(function):
    def wrapper(*args, **kwargs):
        print(round(math.sqrt(function(*args, **kwargs)), 9))
    return wrapper

@square_root
def suma(a, b):
    return a + b
    
suma(10, 10)	# terminl -> 4.472135955
"""
create a function that receives two numbers for example 425 and 46 
and outputs 446, thus by removing the length of the second number from de firs 
and changing it by de second number.
Then add a decorator that add the message "Your updated number is: 
Good Luck!!

"""

def execution_time(func):
    def wrapper(*args, **karg):
        initial_time = datetime.now()
        func(*args, **karg)
        final_time = datetime.now()
        time_enlapsed = final_time - initial_time
        print(f'Time enlapsed {time_enlapsed} seconds')
    return wrapper

def message(func):
    def wrapper(*args, **karg):
        print("Your updated number is: ")
        func(*args, **karg)
    return wrapper

@execution_time
@message
def change(primitive_number, new_number) ->int:
    leng_new_number = len(str(new_number))
    primitive_number_cut = int(primitive_number/(10 ** leng_new_number))
    updated_number = (primitive_number_cut * 10 ** leng_new_number) + new_number
    print(" " * 24 + str(updated_number))



def run():
    primitive_number = 425
    new_number = 46
    change(primitive_number, new_number)       #should output 446

    

if __name__=="__main__":
    run()

Reto 2:

import math

def motivation(func):
    def wrapper(*args, **kwargs):
        print("Hola amigo, este es el resultado de tu operación:")
        print(func(*args, **kwargs))
        print("Sigue adelante, recuerda que la práctica hace al maestro!")
        print("¡No te rindas nunca y nunca pares de aprender!")
    return wrapper
        
@motivation
def multiply(a: int,b: int) -> int:
    return a*b

def sum(a: int,b: int) -> int:
    return a+b
@motivation
def sqrt(a: int) -> float:
    return math.sqrt(a)

if __name__ == '__main__':
    print(str(multiply(8,125))+"\n")
    print(str(sum(8,12))+"\n")
    print(str(sqrt(20))+"\n")

Yo decidí decorar mis operaciones matemáticas con frases que me inspiran. Espero usarlas en mi vida diaria de manera más práctica.

Hice una función que genera listas de tamaño n con números aleatorios entre min y max. El decorador se encarga de ordenar estas listas. Realmente es muy básico y se puede hacer directamente pero no se me ocurría algo más. 😅

Quería hacer una función para tener la temperatura, humedad, altura… de una ciudad dada y con decoradores agregar nuevas funcionalidades, como saber si ir o no a la playa o si llevar sombrilla … pero creo que es una mala implementación de los decoradores, aiuda

import requests, json
 
# ingresamos la API KEY
api_key = 'ddacb260cd156611fd36dd307458bc44'

# direccion web desde donde solicitaremos la informacion
base_url = "ap.openweathermap.org?"
 
# ciudad (se lo mas especifico posible en el nombre)
city_name = 'Mexico'
 
# esta es la URL completa con la informacion concatenada para realizar la petición correcta
complete_url = base_url + "appid=" + api_key + "&q=" + city_name
# Ejecutamos la consulta
response = requests.get(complete_url)
 
# Obtenemos la respuesta en formato JSON
x = response.json()

if x["cod"] == 200:
    # En “main” se encuentra la informacion principal del estado del tiempo
    y = x["main"]
    
    # Almacenamos la temperatura
    temperatura = x['main']['temp']- 273
 
    # presion atmosferica
    current_pressure = y["pressure"]
 
    # humedad
    current_humidity = y["humidity"]


print('La temperatura de la ciudad de ' + x['name'] + ' es de : ' + str(temperatura))


Este código calcula el tiempo que tarda en realizar una transferencia. Debes ingresar el nombre, número de cuenta y la cantidad a tranferir.
Solo simula el proceso básico de una transferencia.

from datetime import datetime

def execution_time(func):
    def wrapper(*args, **kwargs):
        initial_time = datetime.now()
        func(*args, **kwargs)
        final_time = datetime.now()
        result = final_time - initial_time
        print(f'The process took {result.total_seconds()} seconds.')
    return wrapper

@execution_time
def transfer(account: str, balance: int):

    beneficiary = input("Beneficiary's name: ")
    bank_account = int(input("Recipient's bank account: "))
    amount = int(input("Amount you want to transfer: "))
    actual_balance = balance - amount
    if actual_balance < 0:
        print('You do not have enough credit')
    else:
        print(f'You have just transferred ${amount} to {beneficiary}.')
        print(f'Your current balance is ${actual_balance}')

transfer('Alexander', 4000)

Función para calcular el tiempo en llegar a un número de uno en uno.

from datetime import datetime

def execution_time(func):
    def wrapper(*args, **kwargs):
        initial_time = datetime.now()
        func(*args, **kwargs)
        final_time = datetime.now()
        time_elapsed = final_time - initial_time
        print(f'Pasaron {time_elapsed.total_seconds()} segundos en ejecutar el número.')
    return wrapper

@execution_time
def run():
    number = int(input('Dame un número y vemos en cuanto llegamos: '))
    for i in range(0, number):
        i = i + 1
        print(i)

if __name__ == '__main__':
    run()

from datetime import datetime

def execution_time(func):
def wrapper(*args, **kwargs):
initial_time = datetime.now()
func(*args, **kwargs)
final_time = datetime.now()
time_elapsed = final_time - initial_time
print(f’Pasaron {time_elapsed.total_seconds()} segundos’)
return wrapper

@execution_time
def random_func():
for _ in range(1, 10000000):
pass

random_func()

def number_random(func):
    def wrapper(*args, **kwargs):
        os.system('clear')
        print('adivina el numero del 1 al 10')
        number = random.randint(1, 10)
        func(*args, **kwargs)
        if args == number:
            print(f'yes the number is {number}')
        else:
            print(f'Game over the number is {number}')
        
    return wrapper

@number_random
def num(n):
    print(f'your number is {n}')


def run():
    num(2)


if __name__ == '__main__':
    run()

Este es mi aporte

<
clients_list = []
file = "../base/.data.csv"

def save_disc(func):
    def wraper(*args,**kwargs):
        func(*args,**kwargs)
        mode = "a"
        if os.stat(file).st_size == 0:
            mode = "w"
        with open(file,mode=mode,encoding="utf-8") as csvfile:
            writer = csv.DictWriter(csvfile,fieldnames["name","age"])
            if mode == "w":
                writer.writeheader()
            writer.writerows(clients_list)

    return wraper



@save_disc
def create_client(name,age):
    new_client = Client(name,age)
    clients_list.append(new_client.to_dict())
> 

Les presento a continuación el reto libre. Consiste en generar un log por cada ejecución de una función en un archivo de texto .log. El archivo va a contener el nombre de la función, el resultado y la fecha en la que se ejecutó.

Previo al ejercicio se debe tener el archivo file.log en la misma ruta del proyecto, se lo puede mejorar, pero la idea es aplicar los decoradores en algo práctico:

import os
from datetime import datetime

def log_function(func):
    def wrapper(*args, **kwargs):
        THIS_FOLDER = os.path.dirname(os.path.abspath(__file__))
        my_file = os.path.join(THIS_FOLDER, 'file.log')
        date = datetime.now()
        xfile = open(my_file, "a")
        output = func(*args, **kwargs)
        print(output)
        xfile.write(f"Log-{func} - Resultado: {output} Fecha: {date}\n")
        xfile.close()

    return wrapper

@log_function
def suma(a: int, b:int) -> int:
    return (a+b)

@log_function
def resta(a: int, b:int) -> int:
    return (a+b)

@log_function
def multiplica(a: int, b:int)-> int:
    return (a*b)

@log_function
def divide(a: int, b:int)-> float:
    assert b!=0, "No se puede dividir para 0"
    return (a/b)

suma(2,50)
resta(5,2)
multiplica(6,2)
divide(50,2)

Lo que hice fue una función que reciba un texto y que obtenga todos los nombres que “matcheen” con este texto. El decorador que hice fue para hacer que los espacios del texto se transformen en comodines y que esos espacios matcheen con cualquier letra.

from typing import List
import re

NAMES = [
  'Joaquín Cruz',
  'Jessica Cruz',
  'Pablo Martínez',
  'Cuarta Person',
  'Roberto Martínez',
  'Bárbara Jerez'
]

def with_query(func):
  def wrapper(query : str) -> List[str]:
    query = f'.*{query.replace(" ", ".*")}.*'
    return func(query)
  return wrapper

@with_query
def match_names(query):
  ret : List[str] = []
  pattern = re.compile(query, flags=re.IGNORECASE)
  for name in NAMES:
    if pattern.match(name):
      ret.append(name)
  return ret

def run():
  print(match_names('j cruz'))

if __name__ == '__main__':
  run()

Resultado:
['Joaquín Cruz', 'Jessica Cruz']

# Reto: decorador que recibe parámetros
def set_custom_messages(init_msg, final_msg):
    def set_messages(func):
        def wrapper(*args, **kwargs):
            print(init_msg)
            func(*args, **kwargs)
            print(final_msg)
        return wrapper
    return set_messages

@set_custom_messages("Este es el mensaje inicial", "Este es el mensaje final")
def walk(message):
    print(message)

if __name__ == "__main__":
    walk("Estoy caminando")

Buenos días, yo hice un ejemplo sencillo para trabajar con decoradores. Hice un decorador que calculaba el volumen de un prisma en base al área de la figura. Por cierto si alguien sabe como pasarle a un decorador un argumento de entrada además de la función se los agradecería. Aquí dejo mi código.

def volume(func):
    def wrapper(*args, **kwargs):
        height = int(input('Ingrese la altura del prisma: '))
        area = func(*args, **kwargs)
        return area * height
    return wrapper

@volume
def triangule(a: int, b: int)->float:
    return a * b / 2

@volume
def rectangle(a: int, b: int)->int:
    return a * b

def run():
    print('Encontrar el area de un prisma triangular y uno cuadrangular')
    a = int(input('Ingrese el valor de A: '))
    b = int(input('Ingrese el valor de b: '))

    prism_r = rectangle(a,b)
    prism_t = triangule(a,b)

    print('El volumen del prisma cuadrangular es', prism_r)
    print('El volumen del prisma triangular es', prism_t)

if __name__=='__main__':
    run()

Si alguien tiene algún tipo de comentarios de como mejorar mi codigo, sera bien recibido.

Mi primer decorador, calcula el precio de un articulo con descuento.




def percentage_calculator_2(func):
    def wrapper(item_price, item_percentage):
        discount_price = item_price * item_percentage // 100
        print("Tu artículo tiene un descuento de " + str(discount_price) )
        func(item_price, item_percentage)
        final_price = item_price - discount_price
        print("Tu artículo cuesta " + str(final_price) + " después del descuento")

    return wrapper


@percentage_calculator_2
def percentage_calculator (item_price: int, item_percentage: int) -> float:
    print("Estamos trabajando para ti")
    

def run():
    item_price = int(input("¿Que valor tiene tu artículo ? "))
    item_percentage = int(input("¿Cuanto descuento tiene tu artículo ? "))

    percentage_calculator(item_price, item_percentage)



if __name__ == '__main__':
    run()

Código para elegir la cena y un decorador para añadir opciones extra y darle algo mas de variedad:

Yo hice un auto-scatter muy sencillo, básicamente le pasas una función que te regrese una lista de coordenadas, una lista de x y una lista de y y te hace el scatter automáticamente… Simple, pero le veo futuro

def auto_scatter(func):
    def wrapper(*args, **kwargs):
        X = func(*args, **kwargs)
        plt.scatter(X[0], X[1])
        plt.show()
    return wrapper

En este caso lo probé con un generador de puntos aleatorio

@auto_scatter
def generate_random_points():
    x = [floor(random()*101) for _ in range(100)]
    y = [floor(random()*101) for _ in range(100)]

    return x, y

Y listop C: generate_random_points()

Mi código sobre sabor de helado mas contorno como sugar sintatic 😉

def decorador(func):
    """Function decorador"""
    def wrapper(message):
        """Function wrapper"""
        add = input("Peanut contour or chococlate chip? ")
        print(f'Your ice cream is of {message} with {add}')
    return wrapper
        

@decorador
def ice_cream(message):
    """Function message"""
    print(f'The ice cream is of: {message}')


def run():
    """Function start"""
    message = input("Chocolate or Vanilla ice cream? ")
    ice_cream(message)


if __name__ == '__main__':
    run()

En mi opinion creo que los decoradores deberian ser creados para ser usados multiples veces en diferentes programas.
Por lo cual no se me ocurren muchas formas de usarlos a menos que sea en el uso de Frameworks cuyo codigo podria repetirse demaciado en donde serian bastante utiles pero fuera de eso heeee…
no se me ocurren muchas ideas.
 
Por cierto hice este programa hace relativamente poco en el curso CRUD con el profe David Aroesti
en fin lo hice con un FrameWork de C llamado Qt y que funciona con Python y otros lenguajes, el unico caso en donde se me ocurrio poner un @decorador fue en una funcion ejecutadora que siempre se repite de ahi en fuera no se me ocurren mas ideas XD
 
Si quieren ver el código completo y jugar con el, esta en mi github

from QtAgregar import QAgregar
from QtBusqueda import QBusqueda
from QtEditar import QEditar
from QtEliminar import QEliminar
from QtMostrar import QMostrar
from QtMultiplesIndices import QMultiplesIndices
from QtOpciones import QOpciones

from cliente import CLIENTES, AbrirBase_Declientes,GuardarBase_DeClientes
from PyQt5 import QtGui, QtCore
from PyQt5.QtWidgets import QApplication,\
                            QWidget,\
                            QLabel,\
                            QHBoxLayout,\
                            QVBoxLayout

class Ventana_principal(QWidget):
    def __init__(self,lista = None):
        super(QWidget,self).__init__()
        self.propiedades_de_ventana()
        self.iniciador(lista)
        self.interfaz()
        self.conexiones()

    def propiedades_de_ventana(self):
        self.setMinimumWidth(750)


    def iniciador(self,lista):
        self.LISTA_CLIENTES = lista
        self.lista_de_widgets = []
        self.boton_pulsado = None

        self.menu_principal = QOpciones()
        self.tabla_de_clientes = QMostrar()
        self.menu_de_busqueda = QBusqueda()
        self.editar = QEditar()
        self.agregar = QAgregar()
        self.eliminar = QEliminar()
        self.elegir_cliente = QMultiplesIndices()

        imagen = QtGui.QPixmap('./iconos/Python Qt5.png')
        imagen.scaled(50,100)
        self.Imagen = QLabel()
        self.Imagen.setPixmap(imagen)

        self.lista_de_widgets.append(self.menu_de_busqueda)
        self.lista_de_widgets.append(self.editar)
        self.lista_de_widgets.append(self.agregar)
        self.lista_de_widgets.append(self.eliminar)
        self.lista_de_widgets.append(self.Imagen)
        self.lista_de_widgets.append(self.elegir_cliente)
        self.__bloquear(4)


    def __bloquear(self,exepcion = None):
        if exepcion != None:
            self.lista_de_widgets[exepcion].setHidden(False)

        for ind, widget in enumerate(self.lista_de_widgets):
            if ind != exepcion:
                widget.setHidden(True)


    def interfaz(self):
        encabezado = QHBoxLayout()
        encabezado.addWidget(self.menu_principal)

        lateral_izq = QVBoxLayout()
        lateral_izq.addWidget(self.menu_de_busqueda)
        lateral_izq.addWidget(self.elegir_cliente)
        lateral_izq.addWidget(self.editar)
        lateral_izq.addWidget(self.agregar)
        lateral_izq.addWidget(self.eliminar)
        lateral_izq.addWidget(self.Imagen)
        lateral_izq.setAlignment(QtCore.Qt.AlignTop)

        lateral_der = QHBoxLayout()
        lateral_der.addWidget(self.tabla_de_clientes)

        centro = QHBoxLayout()
        centro.addLayout(lateral_izq)
        centro.addLayout(lateral_der)

        self.CUERPO = QVBoxLayout(self)
        self.CUERPO.addLayout(encabezado)
        self.CUERPO.addLayout(centro)

    def conexiones(self):
        self.menu_principal.click[int].connect(self.__activar_funciones)
        self.menu_principal.cancelar.connect(self.__restablecer_funciones)

        self.menu_de_busqueda.click_busqueda[list].connect(self.__encontrado)
        self.menu_de_busqueda.click_cancelar.connect(lambda: self.menu_principal.cancelar.emit(self.boton_pulsado))

        self.elegir_cliente.indice_elegido[int].connect(self.__modificar_eliminar)
        self.elegir_cliente.cancelar.connect(lambda: self.menu_principal.cancelar.emit(self.boton_pulsado))

        self.eliminar.eliminar.connect(self.__mostrar)
        self.eliminar.cancelar.connect(lambda: self.menu_principal.cancelar.emit(self.boton_pulsado))

        self.editar.cambioHecho.connect(self.__mostrar)
        self.editar.cancelar.connect(lambda: self.menu_principal.cancelar.emit(self.boton_pulsado))

        self.agregar.Agregado[dict].connect(self.__agregar)
        self.agregar.Cancelar.connect(lambda: self.menu_principal.cancelar.emit(self.boton_pulsado))

    def __activar_funciones(self, ind = 4):
        self.boton_pulsado = ind
        if ind == 0 or ind == 1 or ind == 3:
            self.__bloquear(0)
            self.menu_de_busqueda.cargar(self.LISTA_CLIENTES)
        elif ind == 2:
            self.__bloquear(ind)
        if ind == 4:
            self.__mostrar()

    def __mostrar(self):
        self.__bloquear(4)
        self.menu_principal._desbloquear(self.boton_pulsado)
        self.tabla_de_clientes.ReCargar(self.LISTA_CLIENTES)
        if self.boton_pulsado != 4:
            GuardarBase_DeClientes()
        


    def __encontrado(self, lista_de_informacion):
        lista_de_diccionarios = lista_de_informacion[1]
        self.tabla_de_clientes.ReCargar(lista_de_diccionarios)
        if self.boton_pulsado == 0: # buscar
            self.menu_principal.cancelar.emit(0)
        else:
            if len(lista_de_informacion[0]) > 1:
                self.__bloquear(5)
                self.elegir_cliente.cargar(lista_de_informacion[0])
            else:
                self.__modificar_eliminar(lista_de_informacion[0][0])

    def __modificar_eliminar(self,ind):
        print(ind)
        self.__bloquear(self.boton_pulsado)
        if self.boton_pulsado == 1: # editar
            self.editar.cargar(self.LISTA_CLIENTES[ind])
        if self.boton_pulsado == 3: # eliminar
            self.eliminar.cargar(self.LISTA_CLIENTES,ind)

    def __agregar(self, diccionario_nuevo):
        self.LISTA_CLIENTES.append(diccionario_nuevo)
        self.__mostrar()


    def __restablecer_funciones(self):
        self.__bloquear()


def DECO_QT_exec(__funcion__):
    import sys
    def window(*argc, **argv):
        app = QApplication(sys.argv)
        __funcion__(*argc,**argv)
        sys.exit(app.exec_())
    return window

@DECO_QT_exec
def ventana(lista:list):
    v = Ventana_principal(lista)
    v.show()

if __name__ == '__main__':
    AbrirBase_Declientes()
    ventana(CLIENTES) ```

Hey que tal, bueno no sé si a alguien le sirva mi código, pero lo único que hace es hacer que es que ejecute una función y espere 5 segundos. Esto lo hice pensando en tipo que le digas algo al usuario (como instrucciones para un juego) y deje el tiempo para que lo lea. Sin más aquí el código

from time import sleep


def amimir(func):
    def mimiendo(*args,**kwargs):
        func(*args,**kwargs)
        sleep(5)
    return mimiendo


@amimir
def texto(text:str)->None:
    print(text)


texto('Heyyy muy buenas a todos, guapisimos, aquí vegetta777 en un nuevo gameplay en directo')

Dejo este snippet para validar permisos de usuarios a cierto recurso. En este snippet se añaden 2 decoradores, el primero para saber si el usuario está logeado y según para saber si el usuario tiene alguno de los permisos necesarios para acceder al recurso. Dejo un par de comentarios donde pueden extender la lógica según su caso de uso


This is my share.

<from datetime import datetime


def check_time(func):
    
    def set(*args, **kwargs):
        time_start = datetime.now()
        func(*args, **kwargs)
        time_end = datetime.now()
        total_delay = time_end - time_start

        print(f'Pasaron en total: {str(total_delay.total_seconds())} segundos')

    return set


@check_time
def run(n: int) -> str:
    if n < 2:
        print('Not a prime number.')
    
    else:
        table = [x for x in range(2, n) if n % x == 0]

        if len(table) > 0: 
            print('Not a prime number.')
        else:
            print('Its a prime number.')


if __name__ == '__main__':
    run(104729)
    > 

Salto de linea con decoradores:

# this function prints a blank line
def new_line_decorator(func):
    # This wrapper function supports parametrized functions
    def wrapper(*args, **kwargs):
        print("\n", end="")
        func(*args, **kwargs)
    return wrapper

# This decorator stores passes say_hello() function to new_line_decorator and calls its wrapper
@new_line_decorator
def say_hello():
    print("Hello World!")

def main():
    print("Hola")
    say_hello()

if __name__ == '__main__':
    main()

El mismo ejercicio de closures ahora con decoradores e incluyendo una variable al decorador lo que hace que se necesite una función anidada extra para capturarla

Yo estoy casi seguro que esto cuenta como decoración. Un programa que se conecta con la API de CMC y trae nombre, s+imbolo y precio del top 10 de tokens

#Este programa hace un request a la api de Coin Market Cap y trae datos del top 10 de tokens

import requests

headers = {
    'X-CMC_PRO_API_KEY': 'e3238e46-ef8e-4dcd-a053-492ea0450877',
    'Accepts': 'application/json'
}

params = {
    'start': '1',
    'limit': '10',
    'convert': 'USD'
}

url = 'https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest'



#Esta decoración recibe a la función get_data la cual se encarga de hacer el request a la API de CoinMarketCap
#Se recibe la data desordenada y en la nested function se ordena y se filtra por los datos que queremos, nombre, token y precio actual
def get_coin_prices_dec(func):
    def wrapper():
        for dict in func():
            print(dict['name'], '-', dict['symbol'], '-', 'Price:',round(dict['quote']['USD']['price'], 2), 'USD') 

    return wrapper

def run():
    @get_coin_prices_dec
    def get_data():
        json = requests.get(url, params=params, headers=headers).json()
        data = json['data']
        #print(data)
        return data
    
    get_data()


if __name__ == '__main__':
    run()

Opinions?

La función emergency_items compara dos listas para verificar si tienen los mismos elementos.

El decorador recibe como parámetro a emergency_items (la cual devolvió una lista) y, con la nested function “wrapper”, la transforma en una cadena de texto he imprime un mensaje en consola.

def list_to_string(func):
    def wrapper(*args, **kuargs):
        strings = '\n \t \03 '.join(func(*args, **kuargs))
        print(f'  You have allredy: \n \t \03 {strings.upper()}')
    return wrapper

@list_to_string
def emergency_itemms() -> list:
    required_items = ["life jakcet", "warm clothes", "medication"]
    items: list = ["life jakcet", "warm clothes", "medication"]
    if items == required_items:
        print("elements ok")
    else:
        print("WARRING! YOU NEED ALL ITEMS")
    return items

if __name__ == "__main__":
    emergency_itemms()

Hola, esto fue lo que se me ocurrió, un decorador que le de formato de dólares a una suma:

def decorador(funcion):
    def contenedor(x,y):
        funcion(x,y)
        suma = x + y
        print("$" + str(suma) + ' USD')
    return contenedor

@decorador
def suma_numeros(x,y):
    pass

suma_numeros(20,50)

MI decorador es una firma para colocar al final del código, yo lo probe en el reto de identificar un numero primo.

def firma (func):
    def agregar_firma(*args, **kwargs):
        func(*args, **kwargs)
        print ('\nEste código ha sido creado por David Castelblanco')
    return agregar_firma

@firma
def is_prime(number: int) -> bool:
    contador: int =0
    for i in range(1, number+1):
        if i == 1 or i==number:
            continue
        if number % i ==0:
            contador +=1
    if contador >0 or number==1:
        print('El numero elegido NO es primo')
    else:
        print('El numero elegido SI es primo')
           


def run():
    number = int(input('Elige un numero para saber si es primo: '))
    is_prime(number)

if __name__=='__main__':
    run()

Hice un programa para asegurar que la longitud de un contraseña sea mayor a 6 caracteres, y si si que confirme la contraseña

#decorador que valida la longitud de la contraseña
def validacion(func):
    def validacion_contraseña(letras):
        if len(letras) > 6:
            print("Contraseña validada cumple la longitud")   
            func(letras)        
        else: 
            print("Contresaña validada no cumple longitud")
            quit()
        return func
    return validacion_contraseña
#ingrese la contraseña y valida que sean iguales
@validacion
def contraseña(letras):
    confirmacion = input("Ingrese la contraseña nuevamente: ")
    if letras == confirmacion:
        print("contraseña asegurada")
    else: 
        print("contraseña no coincide")


contraseña_nueva = input("Ingrese su contraseña: ")
contraseña(contraseña_nueva)

Aqui mi aporte al ejercicio libre con decoradores
A partir de su peso en Kg y su estatura en metros le devuelve su calificacion segun su indice de masa corporal IMC

def imc_grade(func):
    def wrapper(*args, **kwargs):
        n= func(*args, **kwargs)
        match n:
            case x if n > 15 and n < 16.1:
                print("IMC= " + str(x) +  " Delgadez Severa. Debe alimentarse mejor")
            case n if n > 16 and n < 18.6 :
                print("IMC= " + str(x) +  " Delgado. Revise su Alimentación y haga ejercicios")
            case n if n > 18.5 and n < 25.1 :
                print("IMC= " + str(x) +  " Ud. está saludable. Siga asi, cuide su alimentacion y haga ejercicios")
            case n if n > 25 and n < 30:
                print("IMC= " + str(x) +  " Ud. tiene sobrepeso. Comience a hacer ejercicios")
            case n if n > 29.9 and n < 35:
                print("IMC= " + str(x) +  " Ud. tiene obesidad moderada. Debe hacer ejercicios y revisar sus hábitos alimenticios")
            case n if n > 34.9 and n < 40:
                print("IMC= " + str(x) +  " Ud. tiene obesidad severa. Debe hacer ejercicios, cambiar sus hábitos alimenticios y buscar ayuda")
            case n if n > 39.9:
                print("IMC= " + str(x) +  " La obesidad no es buena. Busque ayuda de inmediato. Está a  tiempo de mejorar")
            
    return wrapper

@imc_grade
def calc_imc() -> float:
    peso: float = float(input("Inserte su peso en Kg: "))
    assert type(peso) == float, "Sólo puedes usar números"
    estatura: float = float(input("Inserte su estatura en metros: "))
    assert type(estatura) == float, "Sólo puedes usar números"    
    return round(peso/estatura**2,1)


calc_imc()

Hice una función que imprime cuántos puntos le faltan a los equipos para clasificar (cogí datos de google al 21 de marzo de 2022 en la liga de Colombia), después de actualizar una tabla. Se me ocurrió porque a veces como aficionado uno quiere ver qué podría faltar o qué resultados se necesitan para que el equipo de uno clasifique. La función de actualizar tabla podría usarse siempre en otro script que guarde los resultados reales, por ejemplo, pero en este caso la reutilice. Lo hice sencillo pero sería chévere complementarlo con web scrapping para hacerlo en tiempo real, poder poner más de un resultado, etc 😄

Crear un algoritmo que sume 2 números solo si ambos son capícuas

def is_capicua(func):
    def verify(n: int) -> bool:
        s = str(n)
        return s == s[::-1]
    
    def wrapper(a: int,b:int) -> int:
        if verify(a) and verify(b):
            return func(a,b)
        else:
            raise ValueError("Ambos números deben ser capícuas")
    return wrapper

@is_capicua
def sum(a: int,b: int) -> int:
    return a + b

if __name__ == "__main__":
    print(sum(121,212))
    print(sum(121,213))

Hola dejo mi aporte, en donde utilizo un clousure para indicar que ya acabo el programa, el programa que cree fue una calculadora

def mensaje_ini(func):
  def wrapper(*args,**kwargs):
    func(*args,**kwargs)
    print("Este programa esta termino, mil gracias")
  return wrapper

while True:
  try:
    a = int(input("Por favor ingrese un número: "))
    b = int(input("Por favor ingrese un número: "))
    signo = input("Por favor indique que tipo de operación desea realizar (suma (+),resta(-),multiplicación(*),división(/)):  ")
    
    if signo not in ('+','-','*','/'):
      print("Ingrese una operación valida")
      signo = input("Ingrese una opción de signo valida nuevamente (suma (+),resta(-),multiplicación(*),división(/)): ")

    
    break
  
  except ValueError:
    print("Introduzca números validos y vuelvalo a intentar ")

@mensaje_ini
def calculadora(a,b,signo):
  if signo == '+':
    print(f'la suma de {a} + {b} es igual a: {a+b}')
  elif signo == '-':
    print(f'la suma de {a} - {b} es igual a {a-b}')
  elif signo == '*':
    print(f'la suma de {a} * {b} es igual a {a*b}')
  elif signo == '/':
    print(f'la suma de {a} / {b} es igual a {a/b}')
    
if __name__ == '__main__':
  calculadora(a,b,signo)

Hola a todos! hay retos muy interesantes por ahí. Yo hice un decorador que transforma un número complejo en forma cartesiana a forma polar

from numpy import pi, abs, angle

def show_polar(number):
  print("abs: "+ str(number[0]) + " < " + str(number[1]) + "°")

def polar_notation(func):
  def wrapper(*args, **kwargs):
    number = func(*args, **kwargs)
    r = abs(number)
    theta = angle(number) * 180 / pi
    return [r, theta]
  return wrapper

@polar_notation
def multiply_complex(a, b):
  return a * b

@polar_notation
def sum(a,b):
  return a + b

Hice un decorador que imprime el resultado de una funcion (siempre que esta retorne algun valor), para poder hacer un seguimiento a los resultados devueltos por las funciones sin llenarme de print() por todos lados.

def show_result(identificator):
    def function_identificator(function):
        print(f'{identificator}')
        def wrapper(*args, **kwargs):
            print('Result: ', function(*args, **kwargs))
        return wrapper
    return function_identificator


@show_result('Potencia: ')
def elevate(number, power):
    return number ** power


def run():
    elevate(5,2)


if __name__ == '__main__':
    run()
#output
#Potencia: 
#Result: 25

Hice para sumar n números… sin importar cuantos haya.

# function to calculate the sum of x values
def sum_of(func):
   def wrapper(*args, **kwargs):
      suma = 0
      for i in func(*args, **kwargs):
         assert type(i) == int, 'Necesitamos un número entero para sumar'
         suma += i
      return suma
   return wrapper

@sum_of
def suma(*args):
   return args

# Llamamos a nuestra función
def run():
   print(suma(1,2,3,4,5,6))
   # print(suma(1,2,3,4,5,'6'))

# Creamos nuestro entrypoint
if __name__ == '__main__':
   run()

Aqui les dejo mi codigo Realice Multiplicacion, Suma y Resta de Fracciones con decoradores.

from datetime import datetime
Menu = """"
******RETO DECORADORES*****
Calculando el tiempo de ejecución en:
1. Multiplicacion de Fracciones
2. Division de Fracciones
3. Suma de Fracciones
"""
print(Menu)
def execution_time(func):
    def wrapper(*args, **kwargs):
        initial_time = datetime.now()
        func(*args, **kwargs)
        final_time = datetime.now()
        time_elapsed = final_time - initial_time
        print("Tiempo : "+ str(time_elapsed.total_seconds())+ " Segundos")
    return wrapper


@execution_time
def multiplicacion(a: int, b: int, c: int, d: int)-> int:
    numerador = a*c
    denominador = b*d
    print("Multiplicacion de Fracciones")
    print(f"El resultado es: {numerador}/{denominador} ")
    

@execution_time
def division(a: float, b: float, c: float, d: float)-> float:
    numerador = a*d
    denominador = b*c
    print("División De Fracciones")
    print (f"El resultado es: {numerador}/{denominador} ")
    
    
@execution_time    
def suma(n1: int, n2: int, n3: int, n4: int)->int:
    numerador = n1+n3
    denominador = n4
    print("Suma de Fracciones")
    print(f"El resultado es: {numerador}/{denominador} ")   

multiplicacion(1, 2, 3, 4)
division(4.2, 5.3, 3.2, 9.2)
suma(3, 4, 2, 4)

Que buena clase jaja

El decorador se asegura que la funcion es llamada cuando el usario se ha autenticado

Solución al reto.
Utilizo los decoradores para permitir o denegar la ejecución de la función decorada, dependiendo de si el usuario está listado en el grupo con permisos.

PRIVILEGED_USERS = ['Jose', 'Anna', 'Facundo']
NORMAL_USERS = ['David', 'Nicolás', 'Carlos']

def exec_privileged_rights(func):
    """ This decorator only executes decorated function if user is listed in  PRIVILEGED_USERS """
    def wrapper(*args, **kwargs):
        actual_user = input('Introduce tu usuario: ')
        assert actual_user in PRIVILEGED_USERS, 'El usuario no tiene permisos de acceso'
        func(*args,  **kwargs)
    return wrapper


def exec_normal_rights(func):
    """ This decorator only executes decorated function if user is listed in PRIVILEGED_USERS or in NORMAL_USERS"""
    def wrapper(*args, **kwargs):
        actual_user = input('Introduce tu usuario: ')
        assert actual_user in PRIVILEGED_USERS or actual_user in NORMAL_USERS, 'El usuario no tiene permisos de acceso'
        func(*args,  **kwargs)
    return wrapper


@exec_privileged_rights
def return_secret_info():
    print('Esto es una información confidencial')


@exec_normal_rights
def return_private_info():
    print('Esta información no es confidencial')


def run():
    return_secret_info()

    return_private_info()


if __name__ == '__main__':
    run()

Solo se me ocurrio usar un decorador para validar los cuartos creados en un generador de mapas tipo Rogue-like

from typing import List

ui_habitacion={
    "width":int,
    "height":int,
    "reward":str,
    "type":str,
    "init_enemies":bool
}

generated_rooms:List = []


def validate_room(func):
    def wrapper(*args,**kwargs):
        room:ui_habitacion = func(*args,**kwargs)
        if room["type"]=="treasure":
            assert generated_rooms.count(room)<1, "Hay mas un cuarto del tesoro"
            generated_rooms.append(room)
        return room
    return wrapper

@validate_room
def generate_treasure_room() -> ui_habitacion:
    treasure_room:ui_habitacion = {
        "width":1,
        "height":1,
        "reward":"Daddy Long Legs",
        "type":"treasure",
        "init_enemies":False
    }
    return treasure_room

def run():
    generate_treasure_room()
    print(generated_rooms)
    generate_treasure_room()

if __name__=="__main__":
    run()

Hice este decorador para obtetener descuentos en la compra de un producto de acuerdo a la membresía

def get_porcent_value(membership : str) :
    if membership.lower() == 'bronce':
        return 10
    if membership.lower() == 'plata':
        return 15    
    if membership.lower() == 'oro':
        return 20
        

def price_with_discount(func):
    def wrapper(membership: str, price: float):
        func(membership, price)
        porcent: int = get_porcent_value(membership)
        new_price: float = price - (price * (porcent / 100))
        print('¡Felicidades! Por tu membresía, has ganado ' + str(porcent) + '% de descuento. Tu nuevo precio es:', str(new_price))
    return wrapper


@price_with_discount
def buy_product(membership: str, price: float):
    print('Bienvenido. ¡Estamos de promoción! veamos que has ganado: ')
    print('Membresía: '+ membership)
    print('Precio: '+ str(price))


buy_product('Oro',154.99)
buy_product('Plata',154.99)
buy_product('bronce',154.99)

Yo hice un temporizador que ejecuta una función después de determinado tiempo 😁
.

Aquí un poco más de contenido (decoradores con clases)

https://realpython.com/primer-on-python-decorators/

Mi pequeño aporte, realmente no se me ocurría algún ejercicio xd

def decorador(func):
    def wrapper(*args, **kwargs):
        print("Hola, Bienvenido")
        func(*args, **kwargs)
    return wrapper

def estudio(universidad):
    print(f"Estudias en {universidad}")
estudio=decorador(estudio)

estudio("UANL")

Comparto mi programa, espero retro!, gracias!

Hice un ejemplo de ordenar pizza para utilizar el decorador de tiempo de ejecución como tiempo para preparar tu pedido 😄 Quedo así:

from datetime import datetime
from os import system
import time

chef = """
        ████████                                                          ████████    
    ████▒▒▒▒▒▒▒▒████                                                    ██▒▒░░░░▒▒██  
  ██░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒██                                                ██▒▒░░    ░░▒▒██
██░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██                    ██████████                ██▒▒        ░░██
██░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██      ████████  ██▒▒░░  ░░▒▒██              ██░░        ██  
██░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██  ██▒▒░░░░▒▒████░░      ░░██              ██░░        ██  
██░░  ░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████▒▒░░    ░░▒▒▒▒░░      ░░▒▒██            ██▒▒░░    ██    
  ██░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██░░        ░░▒▒░░░░    ░░▒▒▒▒██            ██▒▒░░  ██    
  ██░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒██░░                  ░░░░  ░░▒▒██            ██▒▒██      
    ██░░    ░░░░░░▒▒▒▒▒▒▒▒░░██▒▒░░    ░░                  ░░██            ██░░██      
      ██░░      ░░░░  ░░░░▒▒██▒▒▒▒░░░░▒▒              ░░  ░░██          ██▒▒██        
        ████░░░░░░░░▒▒▒▒▒▒████▒▒░░░░▒▒░░░░            ▒▒░░▒▒██          ██░░██        
            ████░░░░▒▒▒▒██▒▒  ██░░▒▒▒▒░░░░▒▒▒▒▒▒▒▒      ▒▒██          ██▒▒██          
                ████████████▒▒  ██▒▒▒▒▒▒▒▒░░░░            ██          ██░░██          
                          ████▒▒  ████████░░░░░░            ██  ██████▒▒██            
                            ████▒▒  ▒▒▒▒▒▒▓▓░░░░▒▒▒▒████▒▒▒▒████▒▒▒▒▓▓▒▒██            
                              ████████░░░░░░████░░▓▓░░░░▓▓░░░░▒▒░░░░██████            
                                ██▒▒░░░░░░░░░░░░░░  ██░░  ██░░░░▒▒░░░░░░██            
                                ██▒▒░░░░░░░░░░░░░░▒▒▓▓░░░░▓▓░░░░░░░░░░▒▒██            
                                ██▒▒░░░░░░░░░░░░░░░░██░░░░██░░░░░░▒▒░░▒▒██            
                                  ██▓▓▒▒░░░░░░░░▒▒▒▒░░░░░░░░░░░░░░▒▒░░██              
                                    ██▒▒░░░░░░░░░░░░░░░░▒▒░░░░░░░░░░██                
                                    ██▒▒░░░░░░░░░░░░░░░░▒▒░░░░░░░░░░██                
                                    ██▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░▒▒██                
                                    ██▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░▒▒██                
                                    ██▓▓▒▒░░░░░░░░░░░░░░░░░░░░░░░░██                  
                                      ██▓▓▒▒░░░░░░░░░░░░░░░░░░░░░░██                  
                                      ██▒▒▒▒▒▒░░░░░░░░░░░░░░░░▒▒▓▓▓▓██                
                                    ██▒▒  ▒▒▒▒░░░░▒▒░░░░░░░░▒▒▓▓▒▒▒▒▒▒██              
                                  ██▓▓▒▒▒▒▒▒▒▒▒▒▒▒▓▓▒▒▒▒▒▒▒▒▓▓▒▒▒▒▒▒▒▒▓▓██            
                                  ██▓▓▒▒▒▒▒▒▒▒▒▒▒▒▓▓████▓▓▓▓▓▓▒▒▒▒▒▒▒▒▓▓██            
                                    ████████████████    ████████████████              
"""

pizza = """
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣤⣶⣶⣦⣄⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣿⣿⣿⣿⣿⣿⣷⣦⡀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣷⣤⠀⠈⠙⢿⣿⣿⣿⣿⣿⣦⡀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣿⣿⣿⠆⠰⠶⠀⠘⢿⣿⣿⣿⣿⣿⣆⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣼⣿⣿⣿⠏⠀⢀⣠⣤⣤⣀⠙⣿⣿⣿⣿⣿⣷⡀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⢠⠋⢈⣉⠉⣡⣤⢰⣿⣿⣿⣿⣿⣷⡈⢿⣿⣿⣿⣿⣷⡀
⠀⠀⠀⠀⠀⠀⠀⡴⢡⣾⣿⣿⣷⠋⠁⣿⣿⣿⣿⣿⣿⣿⠃⠀⡻⣿⣿⣿⣿⡇
⠀⠀⠀⠀⠀⢀⠜⠁⠸⣿⣿⣿⠟⠀⠀⠘⠿⣿⣿⣿⡿⠋⠰⠖⠱⣽⠟⠋⠉⡇
⠀⠀⠀⠀⡰⠉⠖⣀⠀⠀⢁⣀⠀⣴⣶⣦⠀⢴⡆⠀⠀⢀⣀⣀⣉⡽⠷⠶⠋⠀
⠀⠀⠀⡰⢡⣾⣿⣿⣿⡄⠛⠋⠘⣿⣿⡿⠀⠀⣐⣲⣤⣯⠞⠉⠁⠀⠀⠀⠀⠀
⠀⢀⠔⠁⣿⣿⣿⣿⣿⡟⠀⠀⠀⢀⣄⣀⡞⠉⠉⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀
⠀⡜⠀⠀⠻⣿⣿⠿⣻⣥⣀⡀⢠⡟⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⢰⠁⠀⡤⠖⠺⢶⡾⠃⠀⠈⠙⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠈⠓⠾⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
"""

soda = """

"""
import cowsay

pizza_flavors = {
    'Pepperoni': 1000000,
    'Pastor' : 60000000,
    'Hawaian' : 30000000
}

soda_flavors = {
    'Cola':1000000,
    'Sprite': 60000000,
    'Mundet': 70000000
}


def clear():
    return system('cls')

def order_time(func):
    def wrapper(*args, **kwargs):
        initial_time = datetime.now()
        func(*args, **kwargs)
        final_time = datetime.now()
        seconds = final_time - initial_time
        print(f'Product: {args[0]}\n\tProcessing time = {str(seconds.total_seconds())} seconds')
    return wrapper

@order_time
def order_pizza(sabor = 'Pepperoni', product = 'Pizza'):
    for k,v in pizza_flavors.items():
        if k == sabor:
            for _ in range(1,v):
                pass

@order_time
def order_soda(sabor = 'Cola', product = 'Soda'):
    for k,v in soda_flavors.items():
        if k == sabor:
            for _ in range(1,v):
                pass

def run():
    flag = True
    while flag:
        print('Write the number of one flavor for your pizza:\n 1. Pepperoni\n2. Pastor\n 3. Special')
        try:
            p_flavor = int(input('Enter a number: '))
            if p_flavor > 3:
                raise ValueError()
            flag = False
        except: 
            clear()
            print('\nSorry! Value not valid\nPlease try again\n')
            pass
    
    clear()
    flag = True

    while flag:
        print('Write the number of one flavor for your soda:\n1. Cola\n 2. Coffe\n 3. Green Tea')
        try: 
            s_flavor = int(input('Enter a number: '))
            if s_flavor > 3: 
                raise ValueError()
            flag = False
        except:
            clear()
            print('\nSorry! Value not valid\nPlease try again\n')
            pass

    clear()

    p_list = list(pizza_flavors)
    s_list = list(soda_flavors)

    p_flavor = p_list[p_flavor-1]
    s_flavor = s_list[s_flavor-1]

    print('We are preparing your order. Please wait . . . ')
    print(chef)
    time.sleep(5)
    clear()
    print(f'\nThank you for your order, here is your {p_flavor} Pizza and a {s_flavor}\n')
    print(pizza)
    time.sleep(5)
    clear()
    order_pizza(p_flavor)
    order_soda(s_flavor)

if __name__=='__main__':
    clear()
    cowsay.cow('Hello Bro!')
    print('This is Kirby\'s Pizza Place\n ¿What would you order today?\n')
    run()
    time.sleep(5)
    clear()
    cowsay.cow('Have a nice day Bro!')

Mi aporte para encontrar una letra o palabra en una variable con texto, utilizando decoradores.

def countstring(func):
    def wrapper(*args, **kwargs): 
        print("Cuenta la cantidad de letras en el texto")
        func(*args,**kwargs)
        return wrapper
    return wrapper

a = """
Esto es una prueba para contar letras o palabras 
en una variable con texto
""" 

@countstring
def contar(texto,p):
    print(f'Hay {texto.count(p)} "{p}" en la variable')


contar(a, "a")

Hola amigos, comparto esta página con 10 Decoradores de Python muy útiles e interesantes:

https://towardsdatascience.com/10-fabulous-python-decorators-ab674a732871

Algunos sirven para acelerar el código usando la caché de Python, otros para que nuestro programa haga algo al terminar. Esto se podría usar por ejemplo al cerrar un Programa y que automáticamente se guarde nuestro Archivo sin perder datos. Y el código es muy fácil. Utilizando el módulo atexit:

from atexit import register

@register
def termin():
    print(" Goodbye!")

Realmente la eficiencia, potencia y elegancia de Python es sorprendente. Espero les sea útil.

Hola a todos aplique las funciones con varios decoradores,

def saludo(func):
    def envoltura(*args, **kwargs):
        return f'hola \n{func(*args, **kwargs)}' 
    return envoltura

def  mayusculas(func):
    def envoltura(*args, **kwargs):
       return func(*args, **kwargs).upper()
    return envoltura  

def aggemogi(func):
    def envoltura(*args, **kwargs):
        return (f'{func(*args, **kwargs)} 🤑🤑') 
    return envoltura        


@aggemogi
@mayusculas
@saludo
def mensaje(nombre):
    return f'{nombre}, recibiste un mensaje'

@mayusculas
@aggemogi
def dollars(dinero: int, cambio:int):
    return f'tienes {round(dinero * cambio,2)} dolares'

def run():
    print(mensaje("Danny"))
    print(dollars(100,7.78))

if __name__ == "__main__":
    run()

HOLA
DANNY, RECIBISTE UN MENSAJE 🤑🤑
TIENES 778.0 DOLARES 🤑🤑

Pues, tal vez no sea muy avanzado y seguro se puede optimizar mucho pero hice un sombrero seleccionador. Ironicamente, la tres veces que ingrese Harry Potter, salió Slytherin. Les dejo el codigo.

import random

def hogwarts(func):
def wrapper(name):
func(name)
houses = (“Gryffindor”, “Slytherin”, “Hufflepuff”, “Ravenclaw”)
selected_house = random.choice(houses)
print("Hola "+ name + “, soy el sombrero seleccionador.”)
print("Tu hogar en Hogwarts será " + selected_house)
return wrapper

@hogwarts
def the_hat(magician):
print("Bienvenido " + magician)
print(“Ponte el sombrero seleccionador”)
input(“Presiona enter cuando estes listo/a…”)

def run():
name = input("Ingresa tu nombre: ")
the_hat(name)

if name == ‘main’:
run()

¡Hola! Mi decorador guarda el resultado de alguna función en un archivo de texto. Por si quiero saber el código de error o para copiar/pegar resultados que me parezcan útiles 😁

import time
from typing import List


def log_to_file(mode: str = "w"):
    def write_to_file(func):
        def wrapper(*args, **kwargs):
            filename = time.strftime("%Y-%M-%d %H:%M")
            with open(filename, mode, encoding="utf-8") as file:
                result = func(*args, **kwargs)
                file.write(str(result))
        return wrapper
    return write_to_file


@log_to_file()
def print_multiples(number: int, limit: int = 100) -> List[int]:
    multiples = [i for i in range(limit + 1) if (i % number == 0)]
    return multiples

@log_to_file()
def beautify_text(message):
    better_message = f"💖{message}💖"
    return better_message

# ---------------------------
# Main function & entry point
# ---------------------------

def run():
    print_multiples(7,150)
    beautify_text("Holi")

if __name__ == '__main__':
    run()

Mi solución al reto.
Por algún motivo que se me escapa, cuando uso el *args y el **kargs no me sale.

def decorator_func(func):
    def wrapper(texto):
        func(texto)
        texto = texto.title()
        texto = texto.strip()
        return texto
    return wrapper


@decorator_func
def input_name(string):
    return f'Bienvenido {string}'



if __name__ == '__main__':
    name = input('Ingresa tu nombre: ')
    print(input_name(name))
~

Les dejo mi aporte, convertir una cadena en mayusculas y minusculas.

def convert_upper_lower(func):
    
    def wrapped(*args, **Kwargs):
        
        string=func(*args, **Kwargs).replace(" ","")
        convert = []
        
        for i in range(len(string)):
            if i%2==0:
                convert.append(string[i].upper())
            else:
                convert.append(string[i].lower())
            print(convert[i])    
    return wrapped


@convert_upper_lower
def character_string(string):
  return string


def run():
    character_string('free challenge')


if __name__=='__main__':
    run()

No es mucho, pero es trabajo honesto.
![](
![](

Solía hacer algo así antes cuando programaba hace años. Esto al final me ayudo a comprender mejor los decoradores. Espero les ayude.

La verdad es que estos días no estoy muy inspirado, pero encontre este ejemplo de Logger en este Sitio Web y es realmente interesante el uso que se le puede dar :

def log(fichero_log):
    def decorador_log(func):
        def decorador_funcion(*args, **kwargs):
            with open(fichero_log, 'a') as opened_file:
                output = func(*args, **kwargs)
                opened_file.write(f"{output}\n")
        return decorador_funcion
    return decorador_log

@log('ficherosalida.log')
def suma(a, b):
    return a + b

@log('ficherosalida.log')
def resta(a, b):
    return a - b

@log('ficherosalida.log')
def multiplicadivide(a, b, c):
    return a*b/c

suma(10, 30)
resta(7, 23)
multiplicadivide(5, 10, 2)

La función decoradora se puede plantear como la función A que recibe a la función parámetro que seria B y a su vez crea la función nested o interior que seria C, así A lleva consigo a B como parámetro y retorna a C como la función donde se crea la lógica para decorar a B

Hice una pequeña calculadora donde el decorador es el que da los encabezados antes de cada operación e individualmente calcula cuanto tiempo tardó haciendo la operación, además en multiplicación utilicé *args para poder enviar el número de parámetros que quisiera para multiplicarlos

from datetime import datetime

def headings(function):
    def write_heading(*args, **kwargs):
        initial_time = datetime.now()
        print('el resultado de su calculo fue: ')
        print(function(*args, **kwargs))
        print('Fin del calculo')
        final_time = datetime.now()
        time_expended = final_time - initial_time
        print ("pasaron "+ str(time_expended.total_seconds()) + "segundos ")

    return write_heading


@headings
def addition(a: int, b: int):
    return a+b


@headings
def subtraction(a: int, b: int, c:int, d:int):
    return a-b-c-d

@headings
def multiplication(*args):
    length = len(args)
    accumulator = 1
    for i in range (length):
        accumulator = args[i] * accumulator

    return accumulator


if __name__ == "__main__":
    addition(1,2)
    subtraction(100,2,3,23)
    multiplication(2,2,2,2,2,2,2,2,2,2)

Este es el resultado en la terminal:

el resultado de su calculo fue:
3
Fin del calculo
pasaron 0.0segundos
el resultado de su calculo fue:
72
Fin del calculo
pasaron 0.0segundos
el resultado de su calculo fue:
1024
Fin del calculo
pasaron 0.001002segundos

Mi aporte

Este ejemplo muestra como mostrar los parámetros deseados:

def decorator_divisor(func):
    def wrapper(*args, **kwargs):
         func(*args,**kwargs)
         return f'It has been calculated the divsors of {args[0]} as a list  and the sum of {args}'
    return wrapper

@decorator_divisor
def divisor (number1,number2):
    divisor_blank = []
    for i in range(1,number1+1):
        if number1 % i == 0:    
            divisor_blank.append(i)
    suma = number1 + number2        
    print(divisor_blank)
    print(number1 + number2)

print(divisor(20,21))

from datetime import datetime

def MostrasCuadroArriba(func):
def wrapper(*args, **kwargs):
func(*args, **kwargs)
print("--------------------------")
print("| |")
print("--------------------------")
return wrapper

@MostrasCuadroArriba

def MostarFecha():
print("La Hora Actual es la: " + str(datetime.now()))

MostarFecha()

Hice un decorador que me diga el tipo de variable que imprime una función

def variables_type(func):
    def wripper(*args,**kwargs):
        func(*args,**kwargs)
        print(type(func(*args,**kwargs)))
    return(wripper)

@variables_type        
def make_list(a: int ,b :int )->list:
    c=[]
    for i in range(a,b+1):
        c.append(i)   
    return c    

make_list(1,9)

Yo hice un programita sencillo para calcular el índice de masa corporal y que te dice si estás bajo de peso, normal, con sobrepeso, obeso o extremadamente obeso.

# This program calculates our Body Mass Index given height and weight.
# Using a decorator it tells us if our weight status (underweight, normal, overweight, obese)


def define_status(func):
    def wrapper(*args, **kwargs):

        # To catch the returned bmi valie from the ffunction
        bmi = func(*args, **kwargs)

        # Conditions to determine the status for a male
        if bmi <= 18.5:
            status = 'Underweight'
        elif bmi > 18.5 and bmi <= 24.9:
            status = 'Normal'
        elif bmi > 24.9 and bmi <= 29.9:
            status = 'Overweight'
        elif bmi > 29.9 and bmi <= 34.9:
            status = 'Obese'
        elif bmi > 29.9 and bmi <= 34.9:
            status = 'Extremly obese'

        #Printing the status
        print(f'Weight status: {status}')

    return wrapper

#With this function we calculate the bmi
@define_status
def bmi_calculator(height: float, weight:float) -> float:
    bmi = weight / (height**2)
    print (f'Your Body Mass Index is :{bmi}')
    return bmi


def run():
    height = float(input('Your height in meters: '))
    weight= float(input('Your weight in kilograms: '))

    bmi_calculator(height,weight)


if __name__ == '__main__':
    run()

Todavía pueden ponerse más detalles como opciones de si eres mujer, niña, niño, try and catch para errores, etc.

El programa calcula el p_value de la distribución de datos aplicando Z-test, adicional se decora para aplicar T-test

mi solución #1:

# EJEMPLO DECORADOR QUE TRANSFORMA A MAYUSCULA EL MENSAJE Y EL NOMBRE
def minusculas(func):
    def wrapper(texto):
        print("Se cambió lo siguiente a minúscula: ")
        return func(texto).lower()
    return wrapper

@minusculas
def mensaje(nombre):
    return "{} HAS RECIBIDO UN MENSAJE".format(nombre)

print(mensaje('CARLOS'))

mi solución #2: (verifica la dimensión de un dataset y si tiene valores nulos…
Se puede mejorar!)

import json
import pandas as pd
from urllib.request import urlopen

# carga del dataframe con la data de la plataforma localbitcoins
url = ("https://jsonplaceholder.typicode.com/comments")
data = json.load(urlopen(url))
df = pd.DataFrame(data=data)

# Decorator function that return the null values of a dataset
def null_values(func):
    def wrapper(df):
        return print(func(df.isnull().sum()))
    return wrapper

@null_values
def shape_of_df(df):
    return df.shape

print(shape_of_df(df))