python - 装饰器有奇怪的行为
问题描述
我正在尝试了解装饰器的工作原理以及如何使用它们,但我遇到了一种奇怪的行为。这个想法是创建一个包装器方法来计算执行时间(我知道,有其他方法可以做到这一点)并包装一个名为“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)
为什么会这样?
解决方案
如评论和文档中所述:
@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))
推荐阅读
- java - 知道为什么 JFrame 会出现这个故障吗?
- node.js - 所有页面都必须使用react吗?
- scrapy - 用 Scrapy 抓取 Airbnb,只需获取一个页面的标题
- html - 如果数字不同,我想通过此按钮添加显示弹出窗口不相等
- firebase - 使用 Github Desktop 将 firebase 功能放到 Github
- macos - 如何在 vim 中存储 golang 模板宏
- python-3.x - 未显示图像文件,但正确获取了 url 位置,我在命令行中也出现类型错误
- java - HTTP 状态 500 - 内部服务器错误 - 服务器遇到阻止其完成请求的意外情况
- gatsby - 使用和不使用 html.js 渲染 Gatsby 页面
- jquery - 将主函数值获取到剑道网格读取函数中