lc88824 发表于 2024-3-10 13:44:06

装饰器顺序和步骤

def add(func):
    def inner():
      x = func()
      return x + 1
    return inner
   
def cube(func):
    def inner():
      x = func()
      return x * x * x
    return inner
   
def square(func):
    def inner():
      x = func()
      return x * x
    return inner
   
@add
@cube
@square
def test():
    return 2
   
print(test())


这个结果65能详解一下 装饰器是如何一步一步运行的吗

FishC 发表于 2024-3-10 13:44:33

当我们调用`test()`函数时,装饰器的运行顺序是从下到上的。也就是说,首先运行`square`装饰器,然后是`cube`装饰器,最后是`add`装饰器。

1. 首先,`@square`装饰器将`square`函数作为参数传递给`test`函数,并且将`test`函数的执行结果作为返回值。
2. `square`装饰器内部定义了一个名为`inner`的函数。在`inner`函数内部,它调用了原始的`test`函数,并将其结果赋给变量`x`。然后,它返回了`x * x`。
3. 接下来,`@cube`装饰器将`inner`函数作为参数传递给`test`函数,并且将`test`函数的执行结果作为返回值。
4. `cube`装饰器内部定义了一个名为`inner`的函数。在`inner`函数内部,它调用了`inner`函数(由`@square`装饰器创建),并将其结果赋给变量`x`。然后,它返回了`x * x * x`。
5. 最后,`@add`装饰器将`inner`函数作为参数传递给`test`函数,并且将`test`函数的执行结果作为返回值。
6. `add`装饰器内部定义了一个名为`inner`的函数。在`inner`函数内部,它调用了`inner`函数(由`@cube`装饰器创建),并将其结果赋给变量`x`。然后,它返回了`x + 1`。
7. 最终,当我们调用`test()`函数时,实际上是调用了`add`装饰器返回的`inner`函数。`inner`函数又调用了`cube`装饰器返回的`inner`函数,最后调用了`square`装饰器返回的`inner`函数。完成所有的运算后,返回结果65。

所以,整个过程可以理解为:

1. `square`装饰器计算结果:2 * 2 = 4。
2. `cube`装饰器计算结果:4 * 4 * 4 = 64。
3. `add`装饰器计算结果:64 + 1 = 65。

希望这个解释能够帮助你理解装饰器的执行顺序和步骤。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

jackz007 发表于 2024-3-10 16:47:33

本帖最后由 jackz007 于 2024-3-10 19:45 编辑

      也许去掉装饰器,更加能够帮助楼主理解装饰器的作用
      下面的代码人工实现装饰器的功能和效果
def add(func):
    def inner():
      x = func()
      return x + 1
    return inner
   
def cube(func):
    def inner():
      x = func()
      return x * x * x
    return inner
   
def square(func):
    def inner():
      x = func()
      return x * x
    return inner
   
#@add                               # 注意这里
#@cube                              # 注意这里
#@square                            # 注意这里
def test():
    return 2
   
#print(test())                      # 注意这里
print(add(cube(square(test)))())    # 注意这里

lc88824 发表于 2024-3-10 21:08:33

FishC 发表于 2024-3-10 13:44
当我们调用`test()`函数时,装饰器的运行顺序是从下到上的。也就是说,首先运行`square`装饰器,然后是`cub ...

叠加装饰器有没有具体教程,举例讲解一下吧

FishC 发表于 2024-3-10 21:08:56

lc88824 发表于 2024-03-10 21:08
叠加装饰器有没有具体教程,举例讲解一下吧

当然!下面我将通过一个具体的例子来讲解叠加装饰器的使用。

假设我们有一个函数`say_hello()`,我们想要给它添加两个装饰器,一个是用于在函数执行前打印一条消息,另一个是用于在函数执行后打印一条消息。

首先,我们定义这两个装饰器:

def before(func):
    def wrapper():
      print("在函数执行前打印一条消息")
      func()
    return wrapper

def after(func):
    def wrapper():
      func()
      print("在函数执行后打印一条消息")
    return wrapper

然后,我们应用这两个装饰器到`say_hello()`函数:

@after
@before
def say_hello():
    print("Hello, World!")

现在,当我们调用`say_hello()`函数时,会按照以下顺序运行装饰器:

1. `@before`装饰器会将`say_hello`函数作为参数传递给`before`装饰器,并将`before`装饰器返回的`wrapper`函数作为`say_hello`函数的新定义。这样,原来的`say_hello`函数就被替换成了`wrapper`函数。

2. `@after`装饰器会将上一步得到的`wrapper`函数作为参数传递给`after`装饰器,并将`after`装饰器返回的`wrapper`函数作为最终的`say_hello`函数的新定义。这样,又一次替换了`say_hello`函数的定义。

最终,当我们调用`say_hello()`函数时,会依次执行以下操作:

1. `@before`装饰器中的`wrapper`函数会在函数执行前打印一条消息。

2. `@after`装饰器中的`wrapper`函数会在函数执行后打印一条消息。

3. `say_hello`函数本身通过`print("Hello, World!")`语句打印出"Hello, World!"。

完整的代码如下所示:

def before(func):
    def wrapper():
      print("在函数执行前打印一条消息")
      func()
    return wrapper

def after(func):
    def wrapper():
      func()
      print("在函数执行后打印一条消息")
    return wrapper

@after
@before
def say_hello():
    print("Hello, World!")

say_hello()# 调用函数

运行以上代码,输出结果为:

在函数执行前打印一条消息
Hello, World!
在函数执行后打印一条消息

希望这个例子能够帮助你理解叠加装饰器的用法!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

lc88824 发表于 2024-3-11 11:45:21

FishC 发表于 2024-3-10 21:08
当然!下面我将通过一个具体的例子来讲解叠加装饰器的使用。

假设我们有一个函数`say_hello()`,我 ...

为什么在函数内外层print打印是按照由下而上输出,里面函数调用就是由上而下的。本例中是哪种情况,这俩情况怎么区分

FishC 发表于 2024-3-11 11:45:39

lc88824 发表于 2024-03-11 11:45
为什么在函数内外层print打印是按照由下而上输出,里 ...

这里会有一个区分的误解。

在 Python 中,函数的执行顺序是按照代码的顺序从上到下依次执行的,也就是说,在函数内部,代码是按照由上而下的顺序执行的。所以,无论是在装饰器内部还是在函数内部,都是由上而下依次执行的。

在你提到的例子中:

def before(func):
    def wrapper():
      print("在函数执行前打印一条消息")
      func()
    return wrapper

def after(func):
    def wrapper():
      func()
      print("在函数执行后打印一条消息")
    return wrapper

@after
@before
def say_hello():
    print("Hello, World!")

say_hello()

先应用的是 `@before` 装饰器,然后才是 `@after` 装饰器。所以,最终的执行顺序是:

1.`@before` 装饰器中的 `wrapper` 函数首先执行,在函数执行前打印一条消息。
2. `@after` 装饰器中的 `wrapper` 函数执行 `func()`,即调用被装饰的函数 `say_hello()`。
3. `say_hello` 函数本身通过 `print("Hello, World!")` 语句打印出 "Hello, World!"。
4. `@after` 装饰器中的 `wrapper` 函数在函数执行后打印一条消息。

这就是为什么你看到的打印顺序是 `@before` 打印在前,`say_hello()` 打印在中间,`@after` 打印在后面。

希望这解释清楚了你的疑惑,如果还有其他问题,请随时提问。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: 装饰器顺序和步骤