Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/347.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
@Python中的装饰器:为什么使用内部定义函数?_Python_Decorator - Fatal编程技术网

@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

我刚刚开始学习Python,我刚刚接触过装饰程序。我编写了以下代码,模仿我所看到的,并且它是有效的:

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)