【python】装饰器学习总结

这是一篇迟到的总结。

以下是我的学习总结步骤:

  • STEP1:

# test1 begin:
# 不是装饰器的装饰器
def deco1(func):
    print "before func() called:"
    func()
    print "after func() called."
    return func

@deco1
def run1():
    print "run1() called!"
    return
# test1 end;

"""
before func() called.
run1() called.
after func() called.
run1() called.
"""

执行完run1()方法后可以看到run1()函数被执行了两次,并不符合要求,所以我称之为不是装饰器的装饰器。严格意义上它也是个装饰器,哈哈。

  • STEP2:

# test2 begin:
# 最简易的装饰器,在函数执行前后附加操作
def deco2(func):
    def _deco():
        print "before func() called:"
        print func()
        print "after func() called."
    return _deco


@deco2
def run2():
    print "run2() called!"
    return "OK"
# test2 end;

"""
before func() called:
run2() called!
OK
after func() called.
"""

这就是一个最简易的装饰器,它完成了装饰器应该完成的任务,但是它只能装饰不带参数的函数。

  • STEP3:

# test3 begin:
# 对带固定参数的函数进行装饰
def deco3(func):
    def _deco(a, b):
        print "before func() called:"
        res = func(a, b)
        print "after func() called."
        return res
    return _deco


@deco3
def run3(a, b):
    print "run3(%s, %s) called!" % (a, b)
    return a + b
# test3 end;

"""
before func() called:
run3(1, 3) called!
after func() called.
4
"""

步骤三能够达到装饰带参数的函数的效果了,但是函数参数如果不一样呢?

  • STEP4:

# test4 begin:
# 对带随机参数的函数进行装饰
def deco4(func):
    def _deco(*a, **b):
        print "before func() called:"
        res = func(*a, **b)
        print "after func() called."
        return res
    return _deco


@deco4
def run4_1(a, b):
    print "run4_1(%s, %s) called!" % (a, b)
    return a + b


@deco4
def run4_2(a, b, c):
    print "run4_2(%s, %s, %s) called!" % (a, b, c)
    return a + b + c['+'] - c['-']
# test4 end;

"""
before func() called:
run4_1(1, 2) called!
after func() called.
3
before func() called:
run4_2(3, 5, {'+': 2, '-': 10}) called!
after func() called.
0
"""

到这里,被装饰的函数的参数个数就是可以变化的了。

  • STEP5:

# test5 begin:
# 让装饰器带参数
def deco5(arg):
    def _deco(func):
        def __deco(*a, **b):
            print "[%s]before %s called:" % (arg, func.__name__)
            res = func(*a, **b)
            print "[%s]after %s called." % (arg, func.__name__)
            return res
        return __deco
    return _deco


@deco5("test5_1")
def run5_1(a, b):
    print "run5_1(%s, %s) called!" % (a, b)
    return a + b


@deco5("test5_2")
def run5_2(a, b, c):
    print "run5_2(%s, %s, %s) called!" % (a, b, c)
    return a + b + c['+'] - c['-']
# test5 end;

"""
[test5_1]before run5_1 called:
run5_1(1, 2) called!
[test5_1]after run5_1 called.
3
[test5_2]before run5_2 called:
run5_2(3, 5, {'+': 2, '-': 10}) called!
[test5_2]after run5_2 called.
0
"""

为了让装饰器本身可以带参数,我们把装饰器的定义结构做了改变,可以看到是三层嵌套的,最外层的入参就是装饰器自己的参数,中间层的入参是被装饰的函数句柄,而最内层的函数入参就是被装饰的函数的入参了。

  • STEP6:

# test6 begin:
# 让装饰器带类参数
def deco6(cls):
    def _deco(func):
        def __deco(*a, **b):
            print "before %s called:" % (func.__name__)
            cls.before()
            res = func(*a, **b)
            cls.after()
            print "after %s called." % (func.__name__)
            return res
        return __deco
    return _deco


class Deco6(object):
    def __init__(self):
        print "Deco6.__init__() called."

    @classmethod
    def before(cls):
        print "Deco6.before() called:"

    @classmethod
    def after(cls):
        print "Deco6.after() called;"


@deco6(Deco6)
def run6_1(a, b):
    print "run6_1(%s, %s) called!" % (a, b)
    return a + b


@deco6(Deco6)
def run6_2(a, b, c):
    print "run6_2(%s, %s, %s) called!" % (a, b, c)
    return a + b + c['+'] - c['-']
# test7 end;

"""
before run6_1 called:
Deco6.before() called:
run6_1(1, 2) called!
Deco6.after() called;
after run6_1 called.
3
before run6_2 called:
Deco6.before() called:
run6_2(3, 5, {'+': 2, '-': 10}) called!
Deco6.after() called;
after run6_2 called.
0
"""

至于带类参数,道理上是一样的,其实字符串参数本身就是类对象,类本身也是对象。

  • STEP7:

# test7 begin:
# 让装饰器来装饰装饰器
@deco5("test7")
@deco6(Deco6)
def run7(a, b, c):
    print "run7_2(%s, %s, %s) called!" % (a, b, c)
    return a + b + c['+'] - c['-']
# test7 end;
"""
[test7]before __deco called:
before run7 called:
Deco6.before() called:
run7_2(8, 5, {'+': 2, '-': 10}) called!
Deco6.after() called;
after run7 called.
[test7]after __deco called.
5

(有双横线会变成粗体,所以上面这段输出我当做代码贴上来了。)这里主要测试一下装饰器的嵌套,至于效果,读者自行根据执行结果总结哈。

下面是我的执行过程,如果对上面输出结果的最后一行数字有疑惑,可以看看我下面的代码,有print的就会多出一行。

if __name__ == '__main__':
    # run1()
    # run2()
    # print run3(1, 3)
    # print run4_1(1, 2)
    # print run4_2(3, 5, {'-': 10, '+': 2})
    # print run5_1(1, 2)
    # print run5_2(3, 5, {'-': 10, '+': 2})
    # print run6_1(1, 2)
    # print run6_2(3, 5, {'-': 10, '+': 2})
    # print run7(8, 5, {'-': 10, '+': 2})
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容

  • 网上很多讲解单个python 装饰器的文章,基础知识我们简单描述。 首先了解装饰器是用来干什么的,装饰器可以增加函...
    小灰灰besty阅读 1,299评论 0 5
  • 呵呵!作为一名教python的老师,我发现学生们基本上一开始很难搞定python的装饰器,也许因为装饰器确实很难懂...
    TypingQuietly阅读 19,517评论 26 186
  • 当你我奋笔疾书在高考的考场 用汗水和双手去追求远方 高三那年的纸条我始终收藏 难以忘却的是你认真的模样 当夕阳落山...
    雨天吖阅读 201评论 1 1
  • 石家庄的冬天总是这样的冷,夜色带着雾霾,寒风夹着清冷,走到熟悉的地方,想起早已离开的人,难免会有感触,我们总说没有...
    安二汶阅读 513评论 0 0
  • 千萬不要以為在與己無關!只要你人還在一天,就不可能無一天與在無關。惟有當你真的消失於這個世界上了,在方才與...
    l左溪l阅读 205评论 0 1