Um decorador em [[Linguagem de programação Python|Python]] é uma função de ordem superior que recebe outra função como argumento, adiciona alguma funcionalidade a ela e retorna a função modificada. Decoradores são uma forma elegante de estender ou modificar o comportamento de funções ou métodos sem alterar sua estrutura original. Eles são aplicados usando o símbolo `@` antes da definição da função.
**Exemplo:**
Vamos criar um decorador que imprime uma mensagem antes e depois da execução de uma função:
```python
def announce(f):
def wrapper():
print("About to run the function")
f()
print("Done with the function")
return wrapper
@announce
def hello():
print("Hello, World!")
hello()
```
**Saída:**
```
About to run the function
Hello, World!
Done with the function
```
**Explicação:**
1. **`announce(f)`:** Esta é a função decoradora. Ela recebe uma função `f` como argumento.
2. **`wrapper()`:** Esta é uma função interna definida dentro de `announce`. Ela envolve a função original `f`.
* Imprime "About to run the function".
* Chama a função original `f()`.
* Imprime "Done with the function".
* Retorna a função `wrapper`.
3. **`@announce`:** Esta sintaxe aplica o decorador `announce` à função `hello`. É equivalente a: `hello = announce(hello)`.
4. **`hello()`:** Quando chamamos `hello()`, na verdade estamos chamando a função `wrapper` retornada por `announce`.
**Como funciona:**
O decorador `announce` "embrulha" a função `hello` com a funcionalidade adicional de imprimir mensagens antes e depois da execução.
**Outro exemplo com argumentos:**
Se a função que você está decorando recebe argumentos, você precisa passar esses argumentos para a função `wrapper`:
```python
def greet(name):
return f"Hello, {name}!"
def uppercase_decorator(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result.upper()
return wrapper
@uppercase_decorator
def greet(name):
return f"Hello, {name}!"
print(greet("Alice")) # Output: HELLO, ALICE!
```
**Explicação:**
* `*args` e `**kwargs`: Permitem que a função `wrapper` receba qualquer número de argumentos posicionais e nomeados, respectivamente.
* `result = func(*args, **kwargs)`: Chama a função original com os argumentos recebidos.
* `return result.upper()`: Converte o resultado para maiúsculas.
**Usos comuns de decoradores:**
* Logging
* Controle de acesso (autenticação, autorização)
* Medição de tempo de execução
* Cache
* Validação de argumentos
**Referência:**
* [Python documentation on decorators](https://peps.python.org/pep-0318/)