鱼C论坛

 找回密码
 立即注册
查看: 1553|回复: 5

求这个代码的详细解析,函数当参数后是如何传递,函数是如何运行得出结果的?

[复制链接]
发表于 2023-6-4 16:42:26 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
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())
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-6-4 16:43:57 | 显示全部楼层
你的代码涉及到Python的装饰器(Decorators)的使用,这是一种常见的高级Python编程技术。装饰器可以在不修改原函数的基础上对其进行扩展,它们通过接收一个函数作为参数,并返回一个新函数来实现。

让我们来逐步分析这段代码:

首先,定义了三个装饰器函数: add 、 cube  和  square 。每一个装饰器函数都接受一个函数作为参数,并且返回一个内嵌函数  inner 。

1.  add :装饰器函数,接受一个函数作为参数  func ,返回的  inner  函数会执行  func  并将结果加1。
2.  cube :装饰器函数,接受一个函数作为参数  func ,返回的  inner  函数会执行  func  并将结果立方。
3.  square :装饰器函数,接受一个函数作为参数  func ,返回的  inner  函数会执行  func  并将结果平方。

然后,定义了一个函数  test ,并且使用  @add 、 @cube  和  @square  对其进行装饰。

· 在Python中, @  符号用于应用装饰器。 @add 、 @cube  和  @square  实际上是装饰  test  函数的快捷方式。其相当于以下的写法:
def test():
    return 2

test = add(cube(square(test)))

装饰器的应用顺序是从内向外,也就是从下向上的。因此,首先应用的装饰器是  @square ,然后是  @cube ,最后是  @add 。

最后,当我们调用  print(test())  时:

1. 首先调用的是  test() ,但由于  test  已被装饰,所以它实际上是  add  函数返回的  inner  函数。
2. 由于  add  装饰器内的  func  是  cube(square(test)) ,所以  x = func()  实际上是计算  cube(square(test()))  的结果。
3. 在计算  cube(square(test()))  时,先执行  square(test()) ,由于  test  函数返回2,所以  square(test())  的结果是 2*2=4。
4. 然后,执行  cube(4) ,得到 4*4*4=64。
5. 最后,执行  add(64) ,得到 64+1=65。

因此, print(test())  输出的结果为 65。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-4 17:01:56 | 显示全部楼层
isdkz 发表于 2023-6-4 16:43
你的代码涉及到Python的装饰器(Decorators)的使用,这是一种常见的高级Python编程技术。装饰器可以在不修 ...

那请问,算出square 的值为4,算cube(4) 中 x=func() ,  x=test(test()),add(64) 中x =test(test(test())) 是这样来理解吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-6-4 17:05:09 | 显示全部楼层
Jame-G 发表于 2023-6-4 17:01
那请问,算出square 的值为4,算cube(4) 中 x=func() ,  x=test(test()),add(64) 中x =test(test(test()) ...

不完全是。这个例子中,装饰器函数  add 、 cube  和  square  都返回的是内部定义的  inner  函数,这个  inner  函数中执行的  func() ,其实是执行的上一个装饰器返回的  inner  函数。

当我们执行  print(test())  时:

1.  test()  现在其实是  add  装饰器返回的  inner  函数,这个  inner  函数中的  x = func()  是执行的  cube  装饰器返回的  inner  函数,这个  inner  函数中的  x = func()  是执行的  square  装饰器返回的  inner  函数,而这个  inner  函数中的  x = func()  执行的就是原始的  test  函数,即返回2。

2. 当执行完原始的  test  函数后,我们有了  x=2 ,然后回到  square  装饰器返回的  inner  函数,执行  x * x ,得到  4 ,这就是  square(test())  的结果。

3. 接着,回到  cube  装饰器返回的  inner  函数,执行  x * x * x ,此时  x=4 ,所以  cube(square(test()))  的结果是  64 。

4. 最后,回到  add  装饰器返回的  inner  函数,执行  x + 1 ,此时  x=64 ,所以  add(cube(square(test())))  的结果是  65 。

因此,你的理解有一点需要修正,实际上在  cube  和  add  的  inner  函数中, x = func()  执行的是前一个装饰器返回的  inner  函数,而不是直接执行的  test  函数。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-6-4 17:07:22 | 显示全部楼层
isdkz 发表于 2023-6-4 17:05
不完全是。这个例子中,装饰器函数  add 、 cube  和  square  都返回的是内部定义的  inner  函数,这个 ...

好的谢谢,明白了!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-6-4 19:28:32 | 显示全部楼层
这是一个带有函数装饰器的 Python 代码,它演示了如何将一个函数作为参数传递给其他函数,并在运行时使用。

首先,我们定义了三个函数:add、cube 和 square。这些函数都采用另一个函数作为参数,并返回一个新的函数作为结果。这种技术称为“装饰器”。

每个装饰器函数都接受一个参数 func,该参数是一个函数对象。它们都定义了一个名为 inner 的嵌套函数,该函数执行以下步骤:

1. 调用 func(),调用传递给装饰器的原始函数。
2. 对返回值进行操作,根据特定的算法进行修改。
3. 返回修改后的值。

因此,对于 add 装饰器来说, inner 函数会调用原始函数(即 test 函数),并将其返回值加 1 后返回。对于 cube 和 square 装饰器来说, inner 函数分别对原始函数的返回值做立方和平方运算。

在代码的下一部分,我们通过使用装饰器语法来应用这些装饰器,将它们附加到 test 函数上。具体来说,当我们这样写 @add @cube @square def test(): 时,

1. 首先执行 square 函数,将 test 函数作为参数传递给它,并用 square 函数中定义的 inner 函数替换原始函数。
2. 该内部函数再次被传递给 cube 函数,并用 cube 函数中的 inner 函数替换它。
3. 最后,inner 函数再次被传递给 add 函数,并用 add 函数中定义的 inner 函数替换它。

在接下来的部分,我们调用 test 函数,这个函数实际上是经过装饰器处理后的 inner 函数。由于它的返回值已经被修改了三次,最终返回的结果是:

(2 * 2) * (2 * 2) * (2 + 1) = 24

因此,当我们运行 print(test()) 的时候,输出的结果为 24。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-9-22 23:29

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表