incrível!! Muito bem explicado com uma didatica excepcional! Só que numca entendi muito bem o funcionamento de decorares por esse mesmo motivo não usava, mas agora que entendi o seu real poder vou usar bastante, mas poderia explicar o *args e o **kwargs? nunca entendi o significado.

Certamente Tallyson!

Os parâmetros *args e **kwargs são antigos companheiros, sendo eles respectivamente uma lista de valores com tamanho variável e um dicionário (chave - valor) de parâmetros.

*args = []

**kwargs = {}

Sendo assim o *args é utilizado para passar os parâmetros declarados na função.

Exemplo:

# Passando via *args os parâmetros declarados
def exemplo (nome, idade):
    print(f'Olá, {nome}, você tem {idade} anos.')

def args (*args):
    exemplo(*args)

args('João', 99)

Execução

Olá, João, você tem 99 anos.

Neste exemplo foi passada a quantidade de parâmetros exata, se for passado um número de parâmetros inferior ou superior a quantidade esperada, será gerada uma exceção.

O **kwargs é utilizado para passar parâmetros adicionais para a função e da mesma forma a função deve ter declarada o parâmetro **kwargs, para permitir os parâmetros adicionais.

# Passando os parâmetros obrigatórios via *args e mais parâmetros adicionais via **kwargs
def exemplo(nome, idade, **kwargs):
    # Imprime todos os parâmetros adicionais
    for arg, value in kwargs.items():
        print(f'{arg} = {value}')

    print(f'Olá, {nome}, você tem {idade} anos.')

def args(*args, **kwargs):
    exemplo(*args, **kwargs)

args('João', 99, pai = 'Carlos', mae = 'Joana', tio = 'Pedro')

Execução

pai = Carlos
mae = Joana
tio = Pedro
Olá, João, você tem 99 anos.

Overloaded

Os parâmetros adicionais passados via *kwargs são muito utilizados para configurar o comportamento do seu método, por exemplo configurar qual formatação utilizar, qual driver utilizar para calcular e etc.

Espero ter ajudado!

Já explicaran o uso dos arga ai

mas um caso de uso interessante que vi no local que trabalho é usar decorators pra implementar retry

A idéia é: caso a função decorada emita um Exception, a mesma será executada mais algumas vezes por meio do controle de um contador recursivo passado como argumento reinjetando.

é curioso

Tipo esse retry ??? ```python def retry(ExceptionToCheck, tries=4, delay=3, backoff=2, logger=None): """Retry calling the decorated function using an exponential backoff. http://www.saltycrane.com/blog/2009/11/trying-out-retry-decorator-python/ original from: http://wiki.python.org/moin/PythonDecoratorLibrary#Retry :param ExceptionToCheck: the exception to check. may be a tuple of exceptions to check :type ExceptionToCheck: Exception or tuple :param tries: number of times to try (not retry) before giving up :type tries: int :param delay: initial delay between retries in seconds :type delay: int :param backoff: backoff multiplier e.g. value of 2 will double the delay each retry :type backoff: int :param logger: logger to use. If None, print :type logger: logging.Logger instance """ def deco_retry(f): @wraps(f) def f_retry(*args, **kwargs): mtries, mdelay = tries, delay while mtries > 1: try: return f(*args, **kwargs) except ExceptionToCheck as e: msg = "%s, Retrying in %d seconds..." % (str(e), mdelay) if logger: logger.warning(msg) else: print(msg) time.sleep(mdelay) mtries -= 1 mdelay *= backoff return f(*args, **kwargs) return f_retry return deco_retry ```
Muito bacana essa ideia. Obrigado por compartilhar.
Muito curioso raton!! Bom saber dessa utilização!