为什么我们 return 在装饰器或嵌套函数中不调用函数

Why we don't call function when we return it in decorator or nested function

当我们在函数内部编写函数时为什么不调用它? return 怎么称呼它?

def my_decorator(func):
    def wrapper():
        print("Something is happening before the function is called.")
        func()
        print("Something is happening after the function is called.")
return wrapper

为什么 return wrapper 而不是 return wrapper() ?当 wrapper 必须带参数时我们做什么?

可以将函数视为 Python

中的值
def foo():
    print("Hello World!")
x = foo
x()

有效 Python 将打印出 Hello World!

扩展这个想法...如果我们想在调用函数之前做一些事情怎么办?那么我们可以这样做:

def foo():
    print("Hello World!")
def do_something_before():
    print("something before")
    foo()
x = do_something_before
x()

但是我们把自己锁定在只能使用 foo 函数。如果我们想为 barfoobar 或任意数量的函数做“之前的事情”怎么办?

我们参数化它!由于我们在“普通”函数上添加了额外的位,即装饰它,我们将这个新函数称为装饰器。

def foo():
    print("Hello World!")

def do_something_before(func): # the decorating function
    def wrap():
        print("something before")
        func()
    return wrap

x = do_something_before(foo)
x()

Python 然后允许我们使用语法糖在我们想要的任何地方执行此操作:

def my_decorator(func):
    def wrapper():
        print("Something is happening before the function is called.")
        func()
        print("Something is happening after the function is called.")
    return wrapper

@my_decorator
def foo():
    print("Hello World!")

装饰器必须接受一个函数,然后被允许再次调用,所以我们不会直接调用 foo,而是 return 里面有 foo 的函数,以便稍后调用 foo 时调用。我们实际上是在调用 wrapper,returned by foo。如果我们在我的装饰器中调用 wrapper,我们将 returning wrapper 的结果而不是 wrapper 本身。这意味着我们不能稍后调用 foo() 因为基本上没有函数可以调用。 我们可以像这样添加参数:

def my_decorator(func):
    def wrapper(*args):
        print("Something is happening before the function is called.")
        func(*args)
        print("Something is happening after the function is called.")
    return wrapper

意思是my_decorator现在可以修饰任何函数。我们还可以指定特定数量的参数。

装饰器用于将一个函数替换为另一个函数,通常是一个以某种方式修改原始函数行为的函数。所以装饰器必须 return 一个应该调用的函数而不是原来的函数。

如果您 return 编辑了 wrapper(),您只需调用一次新的 wrapper 函数并 return 结果。但你真正需要做的是用 wrapper 替换 func,这样每次有人调用 func,他们实际上会调用 wrapper,然后调用 func 根据需要。所以 my_decorator 必须 return wrapper 本身,而不是 wrapper() 的输出。然后,当你使用 my_decorator 作为装饰器时, Python 会自动调用 wrapper 而不是原来的函数。

wrapper 函数应始终采用与 func 相同的参数。因此,如果它需要参数,只需使用与 funcdef wrapper(): 行中采用的参数相同的参数来定义它。