具有奇怪行为的装饰器

Decorators having strange behavior

我正在尝试了解装饰器的工作原理和使用方法,但我遇到了一个奇怪的行为。 这个想法是创建一个包装器方法来计算执行时间(我知道,还有其他方法可以做到这一点)并包装一个名为“cadastra_usuario_no_banco”的方法,这个方法只是休眠和 returns 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())

我从包装纸中得到两倍的印刷品和 returns。

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)

为什么会这样?

如评论和 docs 所述:

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

相当于

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

装饰器是将另一个函数作为参数和 returns 一个新函数的函数。

因此,当您将 @tempo_de_execucao 放在 cadastra_usuario_no_banco 上方并调用 tempo_de_execucao(cadastra_usuario_no_banco) 时,您调用了两次,结果是 tempo_de_execucao(tempo_de_execucao(cadastra_usuario_no_banco))