@Python中的装饰器:为什么使用内部定义函数?
我刚刚开始学习Python,我刚刚接触过装饰程序。我编写了以下代码,模仿我所看到的,并且它是有效的:@Python中的装饰器:为什么使用内部定义函数?,python,decorator,Python,Decorator,我刚刚开始学习Python,我刚刚接触过装饰程序。我编写了以下代码,模仿我所看到的,并且它是有效的: def decorator_function(passed_function): def inner_decorator(): print('this happens before') passed_function() print('this happens after') return inner_decorator @dec
def decorator_function(passed_function):
def inner_decorator():
print('this happens before')
passed_function()
print('this happens after')
return inner_decorator
@decorator_function
def what_we_call():
print('The actual function we called.')
what_we_call()
但后来我写了这样一篇文章,它抛出了错误:
def decorator_function(passed_function):
print('this happens before')
passed_function()
print('this happens after')
@decorator_function
def what_we_call():
print('The actual function we called.')
what_we_call()
那么,为什么我们需要在decorator函数中有内部嵌套函数呢?它有什么用途?只使用第二个的语法不是更简单吗?我没有得到什么
有趣的是,两者都有相同的(正确的)输出,但第二个上也有错误文本,说“TypeError:'NoneType'对象不可调用”
请使用适合刚开始使用Python的人的语言和示例,Python是他的第一种编程语言,也是OOP的新手!)谢谢。Python装饰器基本上只是语法糖。这:
@decorator
def fn(arg1, arg2):
return arg1 + arg2
变成这样:
def fn(arg1, arg2):
return arg1 + arg2
fn = decorator(fn)
也就是说,装饰器基本上接受函数作为参数,并返回“某物”;“某物”与修饰函数的名称绑定
几乎在所有情况下,“某物”都应该是另一个函数,因为预期
fn
将是一个函数(并且可能会像调用函数一样被调用)。原因是,当您包装我们在decorator函数中调用的内容时,执行以下操作:
@decorator_function
def what_we_call():
...
您正在做的是:
what_we_call = decorator_function(what_we_call)
在您的第一个示例中,它之所以有效,是因为您实际上不运行内部函数,您只需初始化它,然后返回新的内部函数(稍后在调用我们调用的函数时将调用该函数):
相反,在第二个示例中,您将运行两个print语句和传递的函数(在本例中我们调用的函数):
def decorator_function(passed_function):
print('this happens before')
passed_function()
print('this happens after')
换句话说,在以下示例中不返回函数:
what_we_call = decorator_function(what_we_call)
运行代码(并看到输出),然后decorator函数返回“None”给我们调用的函数(覆盖原始函数),当调用“None”时,就像Python抱怨的函数一样。因此,decorator函数只是一个“引擎”,每当调用我们调用的函数时都会被调用,但是内部装饰器是传递回来的实际函数吗?所以我可以通过return传回任何东西,只要它是一个函数?所以你甚至可以这样写:
def decorator\u函数(passed\u函数):返回其他函数
并完全椭圆化修饰函数,是吗?对这两个问题都是(如果使用“ellipse”,您的意思是传递的_函数被丢弃,根本不使用,因为被其他_函数替换)。关于注释中的代码格式,我不知道:)嗯。。。因此,在函数上方添加@decorator\u名称基本上表示“嘿,我知道您想使用此函数,但请运行另一个名为decorator\u name的函数,并使用它告诉您(或返回)的函数来代替您调用的原始函数”。装饰器传回的函数可能包含原始函数,也可能不包含。是的,尤其是函数def之前的@decorator_名称也将原始函数本身作为参数传递给修饰函数,以便“扩展”原始函数(通常)。无论如何,是的,您也可以放弃传递的函数并返回一个新函数,而与作为参数传递的函数没有任何关系。
what_we_call = decorator_function(what_we_call)