31-高级特性之装饰器(1)

1. 定义:

Decorator(即装饰器)其实就是闭包实现的一个函数:把{一个待扩展功能的函数Fun}当做参数传入一个外函数Out,在外函数内部定义的内函数In“装饰扩充”Fun,然后返回In。

  • 一句话描述:把一个函数A当参数传入另一个函数B,并返回一个函数C

    def Out(Func):
    def In(args, **kw): #这两个参数其实是给Func()使用的
    print("前置修饰操作 ")
    Func(
    args, **kw) #当前置修饰操作一旦完成,就自动执行Func
    print("后置修饰操作 ")
    return In #把闭包返回出去

    现在一旦执行Out,就会得到In,再执行In(),就会立刻执行前置修饰操作,接下来得到Func()的执行结果并返回出去

    装饰器Out的效果就是:先执行前置操作,再执行Fun(),再执行后置方法

    不用语法糖,先手动模拟下装饰器的运行:

    def fun_1():
    print("I am fun_1 ")
    ret = Out(fun_1) #得到In
    ret() #执行In

    使用语法糖

    @Out #加装饰器Out
    def fun_2():
    print("I am fun_2 ")
    fun_2()

    其实 @Out 等价于 ret = Out(fun_2), fun_2()等价于 ret()

  • Decorator的效果:

  • 遵循“开放封闭原则”:对扩展开放,对已写好的函数封闭
  • 一个装饰器写好了,可到处重用
  • Decorator的应用:
    假设有A函数已经写好了,想为它扩充如下功能:
  1. 引入日志
  2. 函数执行时间统计
  3. 执行函数前预备处理
  4. 执行函数后清理功能
  5. 权限校验等场景
  6. 缓存

实例:

  • 实例1:

    定义Decorator

    def makeBold(func):
    def wrapper():
    return ''+func()+'' #给文本加粗
    return wrapper

    def makeItalic(func):
    def wrapper():
    return ''+func()+'' #把文本设为斜体
    return wrapper

    装饰过程

    @makeBold
    def test1():
    return "I am test1!"

    @makeItalic
    def test2():
    return "I am test2!"

    @makeBold
    @makeItalic
    def test3():
    return "I am test3!"

    调用函数: 要根据装饰器里面对func()的修饰行为 {设置是否需要接受返回值的操作}

    此处需要接受返回值

    r1, r2, r3 = test1(), test2(), test3()
    print(r1, ' ', r2, ' ', r3)

  • func()即可能是无形参,也可能是带各种参数。为了兼容两种情况,采用func(*args, **kw)的方式处理:
  • func()即可能是有返回值,也可能是无返回值。为了兼容两种情况,采用 ret=func(), return ret的方式处理(因为如果函数没有返回值python默认都会return None)
  • 为了处理以上“参数和返回值问题”,可编写一个通用装饰器

    from time import ctime,sleep

    def timefun(func):
    def wrapper(args, **kw): #支持可变参数,关键字参数 {实现了对参数的自适应}
    print("%s called at %s" % (func.name, ctime()))
    ret = func(
    args, **kw) #若有返回值,接受并待会儿返回;若无,返回None
    #...若干操作后
    return ret #实现了对返回值的自适应
    return wrapper

    @timefun
    def test1(): #无参
    print("-----test1----")
    test1()
    sleep(1)
    test1()
    print(' ')

    @timefun
    def test2(a,b): #有参数
    print("%s %s" % (a,b))
    test2(10,20)
    sleep(1)
    test2(20,30)
    print(' ')

    @timefun
    def test3(a,b): #无返回值
    print("%s+%s=%s" % (a,b,a+b))
    ret = test3(100,200)
    sleep(1)
    ret = test3(200,300)
    print(ret, ' ')

    @timefun
    def test4(a,b): #有返回值
    return a -b
    ret = test4(1000,2000)
    print(ret)
    sleep(1)
    ret = test4(2000,3000)
    print(ret, ' ')

原文地址:https://www.cnblogs.com/LS1314/p/8504542.html