首页 > 解决方案 > 装饰器有奇怪的行为

问题描述

我正在尝试了解装饰器的工作原理以及如何使用它们,但我遇到了一种奇怪的行为。这个想法是创建一个包装器方法来计算执行时间(我知道,有其他方法可以做到这一点)并包装一个名为“cadastra_usuario_no_banco”的方法,这个方法只是休眠并返回true。

import time
def tempo_de_execucao(funcao_original):
  def envolucro(*args, **kargs):
    tempo_inicio = time.time()
    retorno = funcao_original(*args, **kargs)
    tempo_total = time.time() - tempo_inicio
    print(" -------- envolucro --------")
    print("A função retornou", retorno)
    print(int(tempo_total), "Segundos para a execução")
  
  return envolucro

@tempo_de_execucao
def cadastra_usuario_no_banco():
  print ("iniciando cadastro de usuário")
  time.sleep(1)
  print ("Cadastro de usuário efetuado com sucesso!")
  return True

但是,当我尝试使用以下说明运行时

a = tempo_de_execucao(cadastra_usuario_no_banco)
print(a())

我得到两倍的打印并从包装器返回。

iniciando cadastro de usuário            # Execution of the wrapped method
Cadastro de usuário efetuado com sucesso!
 -------- envolucro --------             # The decorated execution 
A função retornou True                   # the correct return of the wrapped method
1 Segundos para a execução               # the time of the execution
A função retornou None                   # the strange behavior, that is not supposed to be here
1 Segundos para a execução               # is not supposed to be here too
None                                     # the print of the wrapper method (this is correct)

为什么会这样?

标签: pythonpython-3.xdecoratorpython-decorators

解决方案


如评论和文档中所述:

@dec2
@dec1
def func(arg1, arg2, ...):
    pass

相当于

def func(arg1, arg2, ...):
    pass
func = dec2(dec1(func))

装饰器是接受另一个函数作为参数并返回一个新函数的函数。

@tempo_de_execucao因此,当您将其放在上方 时,您会调用它两次,cadastra_usuario_no_banco并且还会调用tempo_de_execucao(cadastra_usuario_no_banco)它,这导致tempo_de_execucao(tempo_de_execucao(cadastra_usuario_no_banco))


推荐阅读