Decoradores em Python
Os decoradores em Python são funções que recebem outra função como parâmetro e retornam uma nova função como resultado. Eles permitem modificar o comportamento de uma função, os valores de seus parâmetros e seu resultado, sem alterar o código original dessa função.
# definição da função decoradora
def select(input_func):
def output_func(): # definimos uma função que substituirá a original
print("*****************") # adicionamos um texto antes da execução da função original
input_func() # chamamos a função original
return output_func # retornamos a nova função
# definição da função original
@select # aplicação do decorador select
def hello():
print("Hello Programício")
# chamada da função original
hello()Primeiro, definimos a função decoradora, que nesse caso é chamada de select(). O decorador recebe como parâmetro a função à qual será aplicado (neste caso, o parâmetro input_func).
def select(input_func):
def output_func(): # definimos uma função que será executada no lugar da original
print("*****************") # adicionamos um texto antes da execução da função original
input_func() # chamada da função original
return output_func # retornamos a nova funçãoO resultado do decorador é a função local output_func, que chama a função passada como parâmetro (input_func). Para simplificar, antes da chamada de input_func, imprimimos uma sequência de estrelas para decorar a saída.
Depois, definimos uma função padrão à qual o decorador será aplicado. Nesse exemplo, a função hello() apenas imprime uma mensagem no console:
@select # aplicação do decorador select
def hello():
print("Hello Programício")Para aplicar o decorador, usamos o símbolo @ antes da definição da função, seguido do nome do decorador. Assim, select() é aplicado à função hello().
A função hello() é passada como parâmetro para o decorador select(). O decorador retorna uma nova função (output_func), que é a que será executada de fato. O resultado será o seguinte:
***************** Hello Programício
Recebendo parâmetros na função decorada
Um decorador pode receber parâmetros, que são passados para a função decorada. Por exemplo:
# definição da função decoradora
def check(input_func):
def output_func(*args): # com *args capturamos os parâmetros da função original
input_func(*args) # chamamos a função original com os parâmetros
return output_func # retornamos a nova função
# definição da função original
@check
def print_person(name, age):
print(f"Name: {name} Age: {age}")
# chamada da função original
print_person("Tom", 38)Aqui, a função print_person() aceita dois parâmetros: name (nome) e age (idade). O decorador check() é aplicado a essa função.
No decorador, a função retornada (output_func) recebe um conjunto de valores como parâmetros usando *args. Esses valores são os parâmetros originais da função decorada, neste caso, name e age.
def check(input_func):
def output_func(*args): # com *args capturamos os parâmetros da função input_funcEm seguida, passamos esses valores para a função original:
input_func(*args)O resultado será:
Name: Tom Age: 38
Validando Valores de Parâmetros
Podemos usar decoradores para verificar e modificar os valores dos parâmetros, como no caso de uma idade negativa:
# definição da função decoradora
def check(input_func):
def output_func(*args):
name = args[0]
age = args[1] # capturamos o valor do segundo parâmetro
if age < 0: age = 1 # se a idade for negativa, alteramos para 1
input_func(name, age) # passamos os valores para a função
return output_func
# definição da função original
@check
def print_person(name, age):
print(f"Name: {name} Age: {age}")
# chamada da função original
print_person("Tom", 38)
print_person("Bob", -5)Usamos índices para capturar os valores de name e age. Se a idade for negativa, a modificamos para 1. O resultado será:
Name: Tom Age: 38 Name: Bob Age: 1
Obtendo o Resultado da Função
Também podemos capturar e modificar o resultado da função usando decoradores:
# definição da função decoradora
def check(input_func):
def output_func(*args):
result = input_func(*args) # passamos os valores para a função
if result < 0: result = 0 # se o resultado for negativo, retornamos 0
return result
return output_func
# definição da função original
@check
def sum(a, b):
return a + b
# chamada da função original
result1 = sum(10, 20)
print(result1) # 30
result2 = sum(10, -20)
print(result2) # 0A função sum() retorna a soma dos números. O decorador check() verifica o resultado e, se for negativo, retorna 0. O resultado será:
30 0