文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

装饰器是怎么实现的?你学会了吗?

2024-11-28 14:03

关注

至于为什么要有装饰器,我觉得有句话说的非常好,装饰器存在的最大意义就是可以在不改动原函数的代码和调用方式的情况下,为函数增加一些新的功能。

def deco(func):
    print("都闪开,我要开始装饰了")

    def inner(*args, **kwargs):
        print("开始了")
        ret = func(*args, **kwargs)
        print("结束")
        return ret

    return inner

# 这一步等价于 foo = deco(foo)
# 因此上来就会打印 deco 里面的 print
@deco
def foo(a, b):
    print(f"a = {a},b = {b}")
print("---------")
"""
都闪开,我要开始装饰了
---------
"""

# 此时再调用 foo,已经不再是原来的 foo 了
# 而是 deco 里面的闭包 inner
foo(1, 2)
"""
开始了
a = 1,b = 2
结束
"""

如果不使用装饰器的话:

def deco(func):
    print("都闪开,我要开始装饰了")

    def inner(*args, **kwargs):
        print("开始了")
        ret = func(*args, **kwargs)
        print("结束")
        return ret

    return inner

def foo(a, b):
    print(f"a = {a},b = {b}")

foo = deco(foo)
"""
都闪开,我要开始装饰了
"""
foo(1, 2)
"""
开始了
a = 1,b = 2
结束
"""

打印结果告诉我们,装饰器只是类似于 foo=deco(foo) 的一个语法糖罢了。

至于字节码这里就不看了,还是那句话,只是个语法糖,它和我们直接调用 foo=deco(foo) 是等价的,所以理解装饰器(decorator)的关键就在于理解闭包(closure)。

另外函数在被装饰器装饰之后,整个函数其实就已经变了,而为了保留原始信息我们一般会从 functools 模块中导入一个 wraps 函数。当然装饰器还可以写的更复杂,比如带参数的装饰器、类装饰器等等,不过这些都属于 Python 层级的东西了,我们就不说了。

另外装饰器还可以不止一个,如果一个函数被多个装饰器装饰,会有什么表现呢?

def deco1(func):
    def inner():
        return f"{func()}"
    return inner

def deco2(func):
    def inner():
        return f"{func()}"
    return inner

def deco3(func):
    def inner():
        return f"{func()}"
    return inner

@deco1
@deco2
@deco3
def foo():
    return "古明地觉"

print(foo())

解释器还是从上到下解释,当执行到 @deco1 的时候,肯定要装饰了,但它下面不是函数,也是一个装饰器,于是表示:要不哥们,你先装饰。然后执行 @deco2,但它下面还是一个装饰器,于是重复了刚才的话,把皮球踢给 @deco3。

当执行 @deco3 的时候,发现下面终于是一个普通的函数了,于是装饰了。

deco3 装饰完毕之后,foo = deco3(foo)。然后 deco2 发现 deco3 已经装饰完毕,那么会对 deco3 装饰的结果再进行装饰,此时 foo = deco2(deco3(foo));同理,再经过 deco1 的装饰,最终得到了 foo  =  deco1(deco2(deco3(foo)))。

于是最终输出:

古明地觉

所以当有多个装饰器的时候,会从下往上装饰;然后执行的时候,会从上往下执行。

以上就是装饰器相关的内容,可以说非常简单了,甚至有点水文章的嫌疑,因为核心都在上一篇介绍的闭包当中。还是那句话,理解装饰器的关键就在于理解闭包。

来源:古明地觉的编程教室内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯