鱼C论坛

 找回密码
 立即注册
查看: 49|回复: 2

装饰器传递参数的困惑

[复制链接]
发表于 5 天前 | 显示全部楼层 |阅读模式

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

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

x
小甲鱼老师在讲解给装饰器传递参数的时候,例题如下:

import time
   
def logger(msg):
    def time_master(func):
        def call_func():
            start = time.time()
            func()
            stop = time.time()
            print(f"[{msg}]一共耗费了 {(stop-start):.2f}")
        return call_func
    return time_master
   
@logger(msg="A")  
def funA():      
    time.sleep(1)
    print("正在调用funA...")
   
@logger(msg="B")
def funB():
    time.sleep(1)
    print("正在调用funB...")
   
funA()
funB()

我的困惑是在定义funA()函数时,加上的@logger(msg="A")  装饰器,作用是将msg="A"作为参数传递给最外层函数logger(msg)中,但是funA()函数也需要被传递到中间函数time_master(func)中,那funA为何不用像msg=’A’一样同过装饰器的形式进行传递?麻烦大侠指点,谢谢!


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 5 天前 | 显示全部楼层
你提出的关于装饰器传递参数的问题非常好!下面我来解释一下:

当你使用 `@logger(msg="A")` 这样的装饰器时,其实是进行了两次调用:

1. **第一次调用:** `logger("A")`  
   这会返回一个新的装饰器函数 `time_master`。

2. **第二次调用:** `time_master(funA)`  
   这会将被装饰的函数 `funA` 作为参数传递给 `time_master` 函数。

来看详细的代码解释:
import time

def logger(msg):
    def time_master(func):
        def call_func():
            start = time.time()
            func()
            stop = time.time()
            print(f"一共耗费了 {(stop-start):.2f} 秒")
        return call_func
    return time_master

@logger(msg="A")
def funA():
    time.sleep(1)
    print("正在调用funA...")

@logger(msg="B")
def funB():
    time.sleep(1)
    print("正在调用funB...")

funA()
funB()

在这个装饰器模式中,`@logger(msg="A")` 会按以下步骤执行:

1. `logger("A")` 被调用并返回新的装饰器 `time_master`。
2. `time_master(funA)` 被调用并返回新的函数 `call_func`。

所以,这里 `funA()` 最终被替换成了 `call_func`,而 `call_func` 中包含了对 `funA` 的调用逻辑及其他额外行为。

关键在于,装饰器的挂载发生在函数定义时,而不是函数调用时。也就是说,用 `@logger(msg="A")` 装饰 `funA` 仅需要提供一个带参数的装饰器,然后由 Python 负责将被装饰的函数 `funA` 传递给 `time_master` 这个新生成的装饰器。这正是 Python 装饰器的强大之处。

为了更清晰地理解,你可以如下调试打印:
import time

def logger(msg):
    print(f"logger 参数: {msg}")
    def time_master(func):
        print(f"正在装饰函数: {func.__name__}")
        def call_func():
            start = time.time()
            func()
            stop = time.time()
            print(f"一共耗费了 {(stop-start):.2f} 秒")
        return call_func
    return time_master

@logger(msg="A")
def funA():
    time.sleep(1)
    print("正在调用funA...")

@logger(msg="B")
def funB():
    time.sleep(1)
    print("正在调用funB...")

funA()
funB()

输出应为:
logger 参数: A
正在装饰函数: funA
logger 参数: B
正在装饰函数: funB
正在调用funA...
一共耗费了 1.00 秒
正在调用funB...
一共耗费了 1.00 秒

希望以上说明能帮助你清楚理解装饰器传递参数的机制!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 5 天前 | 显示全部楼层
装饰器本质是什么?它本来就是传funA的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-2-5 23:59

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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