装饰器

释义

装饰,即添加额外的修饰,在不改变函数源代码和调用方式的前提下,添加额外的功能。器,在python里面,指定的函数,例如迭代器,生成器,都是函数。装饰器,本质就是函数,功能是为其他函数添加新功能。推荐文章:https://segmentfault.com/a/1190000007837364

装饰器遵循的原则(开放封闭原则)

1.不改变被修饰函数的源代码
2.不改变被修饰函数的调用方式

实现装饰器的原理构成

装饰器=高级函数+函数嵌套+闭包

实现装饰器

例子1:

import datetime
import time

def count1(a,delta):     #附加count1函数  
    if delta < a:
        print(delta)
    else:
        print("hhhhhh")

def logger2(a=5,fun=count1):    #方便为count1函数传参
    def logger1(fn):
        def inner(*args,**kwargs):
            """what fuck"""
            print("gogogo")
            start = datetime.datetime.now()
            ret = fn(*args,**kwargs)      #调用主体函数
            delta = (datetime.datetime.now()-start).total_seconds()
            fun(a,delta)
            return ret
        return inner
    return logger1

@logger2(1)  #add3 = logger1(add3)      #语法糖:@
def add3(x,y):       #主体函数
    return x+y    
print(add3(2,5))

打印结果:

gogogo
0.0
7

例子2:

def wrapper1(func):
    def inner():
        print ('w1,before')
        func()
        print('w1,after')
    return inner

def wrapper2(func):
    def inner():
        print('w2,before')
        func()
        print('w2,after')
    return inner

@wrapper2     #连着两个装饰器,相当于foo = wrapper2(wrapper1(foo))  
@wrapper1
def foo():
    print ('foo')

print(foo())

传参***解密

def Before(request):        				 #1  #15
    print('before') 							 #16
def After(request):							 #2  #23
    print('after')								 #24
def Filter(before_func,after_func):          #3   #5
    def outer(main_func):                    #6   #8
        def wrapper(request):				 #9  #13
            before_result =before_func(request)  #14
            if(before_result !=None):			 #17
                return before_result
            main_result = main_func(request)     #18
            if(main_result !=None): 			 #21
                return main_result
            after_result = after_func(request)   #22
            if(after_result !=None):     		 #25
                return after_result
        return wrapper                       #10
    return outer							 #7		
@Filter(Before,After)                        #4
def Index(request):							 #11 #19
    print('index')							 #20
Index('example')  							 #12

首先是在第3步这里,解释器发现了这个函数,并把它放进了内存里,然后第4步又读到了一个装饰器,它就从内存里找到装饰器的地址返回到了第5步这个装饰器的位置。继续往下读,第6步它又把发现了一个outer函数,于是把outer函数的地址放进了内存里,然后就停止了,因为它很清楚它不是来执行outer的,所以它调过了这个函数并顺序执行了这个函数外面的第一句话:第7步,return outer。这个时候解释器发现这不就是刚刚记下了地址的那个方法么?它就又回来了之前的地址,找到了outer函数。。。就是这样,直到执行到第10步return wrapper,这里我没有写,其实它也是兴冲冲的回到了家wrapper方法那里的,但是它发现下面已经没有它需要记录地址的函数了。所以它把最后的这个wrapper函数的地址返回给了装饰器,也就是装饰器下面的index方法。
这个时候,我们在程序中调用了这个index方法,那么解释器就把我们领到wrapper那里开始执行了,在wrapper里我们可以使用外层函数传过来的方法参数Before和After,这其实就是装饰器参数的秘密了。

附言

装饰器分两部,第一步执行装饰器函数,获取inner函数的标识,在C中就是指向函数的指针,在Python中也就是函数体内存空间的标识,这个标识指向函数体的地址。第二步就是进行更名,标识说换就换,函数体地址不变,只不过换了件衣服,自然不会影响结果。对于三层装饰器函数或者说是带参数的装饰器函数,可以看成装饰器结合的次序,就是先执行最外层的装饰器函数,传入参数,同时返回里层装饰器名。这里的参数可以是函数的标识,函数定义在外面,before_func和after_func就可以随心所欲,作为参数传入

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值