python之装饰器

1.装饰器的特点

装饰器是在闭包上的升级,是传参为函数的闭包

先来看下以下这段代码

def decorate(func): #装饰器接收一个函数作为入参
    print('外层打印测试')
    def inner(): #内部函数
        func() #调用接收的函数
        print('-------刷墙-------')
    print('内层加载完成……')
    return inner #返回内部函数名

@decorate #装饰器
def house(): #被装饰函数
    print('我是毛坯房')

运行下,看下控制台输出

外层打印测试
内层加载完成……

这里奇怪的地方是,在以上代码中我们只是声明了两个函数docorate和house,并没有调用任何函数,运行后控制台竟然会打印出decorate中的信息,原因就在于我们使用了装饰器@decorate

所以装饰器的功能如下:

只要使用了装饰器,就会自动执行以下步骤
1.@decorate下的函数就是被装饰函数
2.被装饰器作为参数传给装饰器decorate
3.底层自动执行decorate函数
4.然后把返回值传给被装饰函数

所以,此时我们在上面的代码最后加上一行,调用house函数,实际上就相当于是调用了inner函数

def decorate(func): #装饰器接收一个函数作为入参
    print('外层打印测试')
    def inner(): #内部函数
        func() #调用接收的函数
        print('-------刷墙-------')
    print('内层加载完成……')
    return inner #返回内部函数名

@decorate #装饰器
def house(): #被装饰函数
    print('我是毛坯房')

house()#调用house,等价于调用inner

运行结果:

外层打印测试
内层加载完成……
我是毛坯房
-------刷墙-------

2.再来看另外一个装饰器,万能装饰器,它可以满足被装饰函数的多种需求

#万能装饰器
import time
def decorate(func):
    def inner(*args,**kwargs):#接收任意个数的参数,以及任何个数的关键字参数
        print('-------正在校验中-------')
        time.sleep(1)
        func(*args,**kwargs) #调用被装饰函数
        print('-------校验完毕-------')
    return inner #返回内部函数名

@decorate
def f1():#无参
    print('----f1-----')

@decorate
def f2(time,n):#两个参数
    print('----f2----',time,n)

@decorate
def f3(students):#列表
    print('----f3----')
    for stu in students:
        print(stu)

@decorate
def f4(n, id='1901'):#1个参数,1个关键字
    print('----f4----',n,id)

a=f1()
b=f2('2019-01-01',2)
c=f3(['lily', 'lucy'])
d=f4(2,id='1902')

运行结果:

-------正在校验中-------
----f1-----
-------校验完毕-------
-------正在校验中-------
----f2---- 2019-01-01 2
-------校验完毕-------
-------正在校验中-------
----f3----
lily
lucy
-------校验完毕-------
-------正在校验中-------
----f4---- 2 1902
-------校验完毕-------

万能装饰器万能的地方在于它可以装饰不同格式的函数,不管被装饰函数传参为无参,列表,还是关键字,都可以在不需要修改装饰器代码的情况下完成不同的功能。

这里主要的功臣就是*args,**kwargs,它表示可以接收任意个数的参数以及关键字。

3.多层装饰器,即给一个函数加多个装饰器的情况,代码如下:

#多层装饰器
#特点:谁距离被装饰函数近就先执行哪个装饰器,装完后再使用下一个装饰器

def decorate1(func):#装饰器1
    print('开始装饰1')
    def inner_func1(*args,**kwargs):
        func(*args,**kwargs)
        print('----刷墙----')
    return inner_func1

def decorate2(func):#装饰器2
    print('开始装饰2')
    def inner_func2(*args,**kwargs):
        func(*args,**kwargs)
        print('----铺地板----')
    return inner_func2

@decorate2
@decorate1
def func():
    print('我是毛坯房')

func()

运行结果为:

开始装饰1
开始装饰2
我是毛坯房
----刷墙----
----铺地板----

4.带参数的装饰器。之前我们有举例带参数的被装饰函数,所以引出了万能装饰器,如果装饰器也带参数呢?

先来看下带参数的装饰器的特点:

带参数的装饰器的特点
1.3层结构(上面的例子都是2层结构)
2.最外层的函数负责接收装饰器参数
3.里面的内容还是原来装饰器的内容

了解特点后,接着来看一个带参数的装饰器的例子: 

#带参数的装饰器

def outer(q):#第一层,负责接收装饰器的参数
    def decorate(func):#第二层,负责接收被装饰函数
        def inner_func(*args,**kwargs):#第三层,负责接收被装饰函数的参数
            func(*args,**kwargs)
            print('铺地板{}块'.format(q))
        return inner_func#返出来第三层
    return decorate#返出来第二层

@outer(q=10)#装饰器带参数q=10
def house(time):
    print('我是毛坯房,{}开始装修'.format(time))

@outer(q=100)#装饰器带参数q=100
def street():
    print('新修的道路名字叫深南大道')

house('2019-12-21')
street()

运行结果为:

我是毛坯房,2019-12-21开始装修
铺地板10块
新修的道路名字叫深南大道
铺地板100块

跟之前的例子相比,带参数的装饰器多了第3层,用来接收装饰器的参数,其他跟之前的2层结构一致,每层都有各自的职责。

第一层,负责接收装饰器的参数
第二层,负责接收被装饰函数
第三层,负责接收被装饰函数的参数

然后依次会返回各自内存函数的函数名。

装饰器的主要特点差不多介绍完了,关于装饰器的实际应用见《python之装饰器应用》

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值