python装饰器学习总结

作者: EldonZhao | 来源:发表于2017-04-13 20:08 被阅读88次

这是一篇迟到的总结。

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

  • 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})

相关文章

  • 装饰器模式

    介绍 在python装饰器学习 这篇文章中,介绍了python 中的装饰器,python内置了对装饰器的支持。面向...

  • python中的装饰器

    python装饰器详解 Python装饰器学习(九步入门) 装饰器(decorator) 就是一个包装机(wrap...

  • python装饰器学习总结

    这是一篇迟到的总结。 以下是我的学习总结步骤: STEP1: """before func() called.ru...

  • Python-02进阶-02装饰器

    Python-00装饰器 装饰器 [toc] TODO 总结 装饰器的作用就是为已经存在的函数或对象添加额外的功能...

  • TypeScript: 类的装饰器(三)

    带参数的类的装饰器 学习 python 的同学应该知道,python 中也有装饰器,而且 python 中的众多框...

  • Python装饰器学习

    Python装饰器学习 Python装饰器学习(九步入门)基础部分根据此文来学习的,接下来将根据此文内容进行整理,...

  • Python装饰器模式学习总结

    装饰器模式,重点在于装饰。装饰的核心仍旧是被装饰对象。 类比于Java编程的时候的包装模式,是同样的道理。虽然概念...

  • python装饰器

    最近在学习python3,对于python的装饰器,多线程以及异步IO有点卡顿。这两天在研究python的装饰器,...

  • 什么是Python装饰器?看小编手把手教学

    讲 Python 装饰器前,我想先举个例子,虽有点污,但跟装饰器这个话题很贴切。 学习Python中有不明白推荐加...

  • python--装饰器--测试程序运行次数以及程序运行时间

    python的装饰器应用极其广泛,在python--学习的章节有所描述,在这里写两个常用的装饰器。 测试程序运行次...

网友评论

    本文标题:python装饰器学习总结

    本文链接:https://www.haomeiwen.com/subject/wfwkbttx.html