Introdução ao Conceito de Decoradores

Beginner

This tutorial is from open-source community. Access the source code

Introdução

Esta seção introduz o conceito de um decorator (decorador). Este é um tópico avançado, do qual apenas arranharemos a superfície.

Este é um Lab Guiado, que fornece instruções passo a passo para ajudá-lo a aprender e praticar. Siga as instruções cuidadosamente para completar cada etapa e ganhar experiência prática. Dados históricos mostram que este é um laboratório de nível intermediário com uma taxa de conclusão de 77%. Recebeu uma taxa de avaliações positivas de 100% dos estudantes.

Exemplo de Logging (Registro)

Considere uma função.

def add(x, y):
    return x + y

Agora, considere a função com algum logging (registro) adicionado.

def add(x, y):
    print('Calling add')
    return x + y

Agora, uma segunda função também com algum logging (registro).

def sub(x, y):
    print('Calling sub')
    return x - y

Observação

Observação: É um pouco repetitivo.

Escrever programas onde há muita replicação de código é frequentemente muito irritante. São tediosos de escrever e difíceis de manter. Especialmente se você decidir que quer mudar como funciona (isto é, talvez um tipo diferente de logging (registro)).

Código que faz logging (registro)

Talvez você possa criar uma função que cria funções com logging (registro) adicionado a elas. Um wrapper (envoltório).

def logged(func):
    def wrapper(*args, **kwargs):
        print('Calling', func.__name__)
        return func(*args, **kwargs)
    return wrapper

Agora use-o.

def add(x, y):
    return x + y

logged_add = logged(add)

O que acontece quando você chama a função retornada por logged?

logged_add(3, 4)      ## Você vê a mensagem de logging aparecer

Este exemplo ilustra o processo de criação de uma chamada função wrapper (envoltório).

Um wrapper (envoltório) é uma função que envolve outra função com alguns pedaços extras de processamento, mas, de outra forma, funciona exatamente da mesma maneira que a função original.

>>> logged_add(3, 4)
Calling add   ## Saída extra. Adicionada pelo wrapper
7
>>>

Nota: A função logged() cria o wrapper (envoltório) e o retorna como resultado.

Decoradores

Colocar wrappers (envoltórios) em torno de funções é extremamente comum em Python. Tão comum que existe uma sintaxe especial para isso.

def add(x, y):
    return x + y
add = logged(add)

## Sintaxe especial
@logged
def add(x, y):
    return x + y

A sintaxe especial executa exatamente as mesmas etapas mostradas acima. Um decorador é apenas uma nova sintaxe. Diz-se que ele decora a função.

Comentário

Existem muitos detalhes mais sutis sobre decoradores do que o que foi apresentado aqui. Por exemplo, usá-los em classes. Ou usar múltiplos decoradores com uma função. No entanto, o exemplo anterior é uma boa ilustração de como seu uso tende a surgir. Normalmente, é em resposta a código repetitivo que aparece em uma ampla gama de definições de funções. Um decorador pode mover esse código para uma definição central.

Exercício 7.10: Um decorador para medição de tempo

Se você define uma função, seu nome e módulo são armazenados nos atributos __name__ e __module__. Por exemplo:

>>> def add(x,y):
        return x+y

>>> add.__name__
'add'
>>> add.__module__
'__main__'
>>>

Em um arquivo timethis.py, escreva uma função decoradora timethis(func) que envolve uma função com uma camada extra de lógica que imprime quanto tempo leva para uma função ser executada. Para fazer isso, você envolverá a função com chamadas de medição de tempo como esta:

start = time.time()
r = func(*args,**kwargs)
end = time.time()
print('%s.%s: %f' % (func.__module__, func.__name__, end-start))

Aqui está um exemplo de como seu decorador deve funcionar:

>>> from timethis import timethis
>>> @timethis
def countdown(n):
    while n > 0:
        n -= 1

>>> countdown(10000000)
__main__.countdown : 0.076562
>>>

Discussão: Este decorador @timethis pode ser colocado na frente de qualquer definição de função. Assim, você pode usá-lo como uma ferramenta de diagnóstico para ajuste de desempenho.

Resumo

Parabéns! Você concluiu o laboratório de Decoradores de Funções. Você pode praticar mais laboratórios no LabEx para aprimorar suas habilidades.