鱼C论坛

 找回密码
 立即注册
查看: 1439|回复: 12

[已解决]装饰器原理

[复制链接]
发表于 2023-8-11 14:45:59 | 显示全部楼层 |阅读模式

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

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

x
#下面是两段代码,都可以完成一个小程序的运行时间测定,前者使用了装饰器,后者没有
问题:在实际应用中,明明都是一行代码,为什么装饰器会比较受青睐(准大学生,很多地方想不出来就在论坛发帖了)
import time
    
def time_master(func):
    def call_func():
        print("开始运行程序...")
        start = time.time()
        func()
        stop = time.time()
        print("结束程序运行...")
        print(f"一共耗费了 {(stop-start):.2f} 秒。")
    return call_func
    
def myfunc():
    time.sleep(2)
    print("I love FishC.")
    
myfunc = time_master(myfunc)
myfunc()


import time
    
def time_master(func):
    def call_func():
        print("开始运行程序...")
        start = time.time()
        func()
        stop = time.time()
        print("结束程序运行...")
        print(f"一共耗费了 {(stop-start):.2f} 秒。")
    return call_func
    
@time_master
def myfunc():
    time.sleep(2)
    print("I love FishC.")
    
myfunc()

最佳答案
2023-8-11 14:46:31
装饰器是Python中一种用于修改函数行为的特殊语法。它可以在不改变函数定义的情况下,对函数进行额外的功能扩展。

在上述代码中,第一个示例中的装饰器使用了函数调用的方式,即通过 myfunc = time_master(myfunc) 将 myfunc 函数传递给 time_master 函数进行装饰。这样,在调用 myfunc() 时,实际上是调用了装饰后的 call_func 函数,从而实现了在函数执行前后打印开始和结束信息的功能。

而第二个示例中的装饰器使用了 @ 符号的语法糖形式,即在 myfunc 函数定义前加上 @time_master ,表示将 myfunc 函数传递给 time_master 函数进行装饰。这样,在调用 myfunc() 时,同样是调用了装饰后的 call_func 函数。

为什么装饰器比较受青睐呢?主要有以下几个原因:

1. 代码简洁:使用装饰器可以将额外的功能与原函数分离,使得代码更加清晰、简洁,易于阅读和维护。

2. 代码复用:装饰器可以被多个函数共享使用,避免了在每个函数中重复编写相同的功能代码。

3. 动态扩展:装饰器可以在不修改原函数定义的情况下,对函数的功能进行动态扩展。这意味着可以随时添加、删除或修改装饰器,从而改变函数的行为。

4. 避免修改原函数:使用装饰器可以避免直接修改原函数的定义,从而保持原函数的纯粹性,减少出错的可能性。

综上所述,装饰器在实际应用中受到青睐的原因主要是因为它能够简化代码、提高代码复用性、实现动态扩展,并且避免直接修改原函数定义。这使得代码更加优雅、灵活和易于维护。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2023-8-11 14:47:18 | 显示全部楼层
我要怎么删掉帖子呀,我应该发两段代码的,搞到一起了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-11 14:46:19 | 显示全部楼层
装饰器是一种Python语法糖,用于增强或修改函数的功能。它可以将一个函数作为参数,然后返回一个经过修饰的函数。

在你给出的代码示例中,装饰器 time_master 被用于测量程序运行时间。这个装饰器可以将计算程序运行时间的逻辑与原始函数分离开来,提高了代码的可读性和可维护性。

对比两个示例代码:
import time

def time_master(func):
    def call_func():
        print("开始运行程序...")
        start = time.time()
        func()
        stop = time.time()
        print("结束程序运行...")
        print(f"一共耗费了 {(stop-start):.2f} 秒。")
    return call_func

def myfunc():
    time.sleep(2)
    print("I love FishC.")

myfunc = time_master(myfunc)
myfunc()
import time

def time_master(func):
    def call_func():
        print("开始运行程序...")
        start = time.time()
        func()
        stop = time.time()
        print("结束程序运行...")
        print(f"一共耗费了 {(stop-start):.2f} 秒。")
    return call_func

@time_master
def myfunc():
    time.sleep(2)
    print("I love FishC.")

myfunc()

在第一个示例中,我们通过调用 time_master(myfunc)myfunc 函数传递给装饰器,并将返回的修饰函数赋值给了 myfunc。然后我们调用 myfunc(),实际上是在调用被装饰后的函数 call_func()

在第二个示例中,我们使用 @time_master 将装饰器直接应用到 myfunc 函数上。这样,每次调用 myfunc() 时,都会自动应用装饰器的逻辑。

使用装饰器的好处是可以避免在每个需要测量运行时间的函数中重复编写计时逻辑。通过将计时逻辑封装在装饰器中,我们可以在任何需要测量运行时间的函数上直接应用装饰器,提高了代码的重用性和可维护性。

希望这个解释对你有帮助。如果还有其他问题,请随时提问。
如果问题已经解决,请设置最佳答案
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2023-8-11 14:46:31 | 显示全部楼层    本楼为最佳答案   
装饰器是Python中一种用于修改函数行为的特殊语法。它可以在不改变函数定义的情况下,对函数进行额外的功能扩展。

在上述代码中,第一个示例中的装饰器使用了函数调用的方式,即通过 myfunc = time_master(myfunc) 将 myfunc 函数传递给 time_master 函数进行装饰。这样,在调用 myfunc() 时,实际上是调用了装饰后的 call_func 函数,从而实现了在函数执行前后打印开始和结束信息的功能。

而第二个示例中的装饰器使用了 @ 符号的语法糖形式,即在 myfunc 函数定义前加上 @time_master ,表示将 myfunc 函数传递给 time_master 函数进行装饰。这样,在调用 myfunc() 时,同样是调用了装饰后的 call_func 函数。

为什么装饰器比较受青睐呢?主要有以下几个原因:

1. 代码简洁:使用装饰器可以将额外的功能与原函数分离,使得代码更加清晰、简洁,易于阅读和维护。

2. 代码复用:装饰器可以被多个函数共享使用,避免了在每个函数中重复编写相同的功能代码。

3. 动态扩展:装饰器可以在不修改原函数定义的情况下,对函数的功能进行动态扩展。这意味着可以随时添加、删除或修改装饰器,从而改变函数的行为。

4. 避免修改原函数:使用装饰器可以避免直接修改原函数的定义,从而保持原函数的纯粹性,减少出错的可能性。

综上所述,装饰器在实际应用中受到青睐的原因主要是因为它能够简化代码、提高代码复用性、实现动态扩展,并且避免直接修改原函数定义。这使得代码更加优雅、灵活和易于维护。

点评

我很赞同!: 5.0
我很赞同!: 5
带佬!!!  发表于 2023-8-11 14:52
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 2 反对 0

使用道具 举报

发表于 2023-8-11 14:48:07 | 显示全部楼层
本帖最后由 陶远航 于 2023-8-11 14:49 编辑
不枉风来水顺 发表于 2023-8-11 14:47
我要怎么删掉帖子呀,我应该发两段代码的,搞到一起了


别人回复了你就不能删了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-11 14:49:25 | 显示全部楼层
不枉风来水顺 发表于 2023-8-11 14:47
我要怎么删掉帖子呀,我应该发两段代码的,搞到一起了

你可以先把帖子改成“已解决”,然后发一个新的求助帖
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-11 14:50:01 | 显示全部楼层
不枉风来水顺 发表于 2023-8-11 14:47
我要怎么删掉帖子呀,我应该发两段代码的,搞到一起了

可以编辑,点帖子下面的“编辑”
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-8-11 14:53:30 | 显示全部楼层
陶远航 发表于 2023-8-11 14:48
别人回复了你就不能删了

ok
明白了,论坛大腿!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-8-11 14:54:00 | 显示全部楼层
tommyyu 发表于 2023-8-11 14:50
可以编辑,点帖子下面的“编辑”

谢谢大佬指导
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-11 15:04:40 | 显示全部楼层
抵制 aiqqqqqwq
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-8-11 15:09:52 | 显示全部楼层

你不会是想说上面的是AI吧,不会吧!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-11 15:19:02 | 显示全部楼层
不枉风来水顺 发表于 2023-8-11 15:09
你不会是想说上面的是AI吧,不会吧!

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-9-21 22:01

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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