鱼C论坛

 找回密码
 立即注册
查看: 2990|回复: 16

[作品展示] 函数加速引擎——装饰器。

[复制链接]
发表于 2016-10-20 14:05:15 | 显示全部楼层 |阅读模式

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

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

x

Python的很多源码里经常会看到
@abc
def  f():
        return 'fishc'
这样的语句。

其中紧跟在@后面的就是装饰器了。

在说装饰器之前,先来看看闭包这个东西。

小甲鱼老师在20讲时说过闭包,课后题传送门。


搞明白这段:
def funOut():
    def funIn():
        print('宾果!你成功访问到我啦!')
    return funIn()

怎么访问到 funIn?

答案是:
funOut()
------
def funOut():
    def funIn():
        print('宾果!你成功访问到我啦!')
    return funIn

怎么访问到 funIn?

答案是:
funOut()()

区别在于 funOut后面跟了一个()与两个()。
funOut,funIn是函数
funOut(),funIn()呢,是执行函数

如果你打印funOut你会看到一串内存地址,
funOut()你会看到这个函数执行后的返回值


进阶的需求。
有这么一个函数。
def html_content():

    return 'i love fishc.'

这个函数返回 'i love fishc.',
现在我们需要将这串字符串放在p标签, b标签与em标签下组成<p><b><em>i love fishc.</em></b></p>。

很简单嘛,
def html_content():

    return '<p><b><em>i love fishc.</em></b></p>'

这时我们又需要将这串字符串放在a标签下组成<a>i love fishc.</a>。

然后我们再次更改html_content函数。

这时又一个人需要把它放在div标签下。

如果我们只有几行代码还很容易修改,当代码多了之后,修改源代码并不划算。

这时候,我们就可以用装饰器来完成这个工作。

def add_em(func1):
    def funin():
        return '<em>{0}</em>'.format(func1())

    return funin
我们定义一个叫add_em的新函数。

作用自然是添加一个em标签。

同时我们将原始html_content函数上面放上装饰器。
@add_em
def html_content():

    return 'i love fishc.'

print(html_content())

你觉得会出现什么?

没错就是变成这样了。
<em>i love fishc.</em>
我们没有修改原始代码就实现了修改原始代码的需求!

原理是什么?

@add_em 相当于 add_em(html_content)

之后我们调用 html_content时,就变成了这样。
html_content()

首先 add_em(html_content) - > funin   函数。
之后 funin + () -> funin()   执行函数。



如法炮制!
def add_em(func1):
    def funin():
        return '<em>{0}</em>'.format(func1())

    return funin

def add_b(func1):
    def funin():
        return '<b>{0}</b>'.format(func1())

    return funin

def add_p(func1):
    def funin():
        return '<p>{0}</p>'.format(func1())

    return funin


@add_p
@add_b
@add_em
def html_content():

    return 'i love fishc.'

print(html_content())
<p><b><em>i love fishc.</em></b></p>
不仅完成了需求,代码也很简洁,还可以重用!


参数!参数!

很多情况下函数都是有参数的,装饰器怎么带参数嘛。
def html_content(arg):

    return 'i love fishc.{0}'.format(arg)

只需要将内层函数加上参数就好了。
def add_em(func1):
    def funin(arg):
        return '<em>{0}</em>'.format(func1(arg))

    return funin

为什么会是这样?

上面说到 加上装饰器之后其实就是变成
             add_em(html_content)(arg)
对应返回       funin    (arg)

那么就是给内层函数加上参数咯,两个,三个,n个都是这样。


装饰器是否可以被执行?
def add_em(func1):
    def funin(arg):
        def funinin(arg):
            return '<em>{0}</em>'.format(func1(arg))
        return funinin
    return funin

def a(arg):
    return '5'

@add_em(a)
def html_content(arg):
    return 'i love fishc.{0}'.format(arg)


我们知道了@add_em就是 add_em(html_content),
那@add_em(a)也就变成了add_em(a)(html_content),

那是否也会向函数一样可以加多个()表示执行?

答案是否定的,会提示语法错误。
@add_em(a)(a)

    @add_em(a)(a)
              ^
SyntaxError: invalid syntax



评分

参与人数 3荣誉 +20 鱼币 +20 贡献 +18 收起 理由
SixPy + 5 + 5 + 5 热爱鱼C^_^
冬雪雪冬 + 10 + 10 + 10 感谢楼主无私奉献!
拈花小仙 + 5 + 5 + 3 感谢楼主无私奉献!

查看全部评分

本帖被以下淘专辑推荐:

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

使用道具 举报

发表于 2016-11-4 13:50:26 | 显示全部楼层
学习学习
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-11-4 14:01:11 | 显示全部楼层
学习一下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-12-23 17:04:43 | 显示全部楼层
这个厉害
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-12-23 22:03:48 | 显示全部楼层
不错
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

头像被屏蔽
发表于 2016-12-23 23:38:26 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-12-23 23:56:03 | 显示全部楼层
挺好的额
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-12-24 23:32:38 | 显示全部楼层
学习
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2016-12-28 19:12:27 | 显示全部楼层
感谢分享
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-2-23 14:46:11 | 显示全部楼层
这个说得很易懂
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-3-14 23:57:44 From FishC Mobile | 显示全部楼层
总算大概懂了,快绕懵了,谢谢分享
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-3-28 10:33:19 | 显示全部楼层
学习
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2017-3-28 13:27:05 | 显示全部楼层
@add_em 相当于 add_em(html_content)

之后我们调用 html_content时,就变成了这样。
html_content()

首先 add_em(html_content) - > funin   函数。
之后 funin + () -> funin()   执行函数
这一部分是难点 好难理解啊?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-7-22 19:01:59 | 显示全部楼层
很好,多谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-8-10 10:57:26 | 显示全部楼层
收藏学习
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-10-7 00:56:20 | 显示全部楼层
感谢 终于有点懂装饰器了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-2-18 22:08:48 | 显示全部楼层
受教了,写的很清楚
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-23 01:57

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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