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ção
O 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_func
Em 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) # 0
A 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