自学Python4.3-装饰器固定格式

自学Python之路-Python基础+模块+面向对象
自学Python之路-Python网络编程
自学Python之路-Python并发编程+数据库+前端
自学Python之路-django

自学Python4.3-装饰器固定格式

1.装饰有返回值的装饰器

import  time
print(time.time())

def timmer(f):    #装饰器函数
    def inner():
        start = time.time()
        ret = f()       #被装饰的函数
        end = time.time()
        print(end - start)
        return ret
    return inner

@timmer         #语法糖 @装饰器函数名
def func():     #被装饰的函数
    time.sleep(0.01)
    print('我好喜欢大家啊~')
    return '新年好'
# func = timmer(func)
ret = func()   #inner()
print(ret)  

以上代码:
   执行timmer(func), 返回inner  (此时此刻func就是inner)  执行func的时候就是执行inner, 所以在inner里面加个返回值

2. 装饰带参数函数的装饰器

2.1 如果被装饰函数有参数, 有一个参数:

import  time
print(time.time())

def timmer(f):    #装饰器函数
    def inner(a):
        start = time.time()
        ret = f(a)       #被装饰的函数
        end = time.time()
        print(end - start)
        return ret
    return inner

@timmer         #语法糖 @装饰器函数名
def func(a):     #被装饰的函数
    time.sleep(0.01)
    print('我好喜欢大家啊',a)
    return '新年好'
# func = timmer(func)
ret = func(1)   #inner()
print(ret)

2.2  如果被装饰函数有参数, 有2个参数:

import  time
print(time.time())

def timmer(f):    #装饰器函数
    def inner(a,b):
        start = time.time()
        ret = f(a,b)       #被装饰的函数
        end = time.time()
        print(end - start)
        return ret
    return inner

@timmer         #语法糖 @装饰器函数名
def func(a,b):     #被装饰的函数
    time.sleep(0.01)
    print('我好喜欢大家啊',a,b)
    return '新年好'
# func = timmer(func)
ret = func(2598,2417)   #inner()
print(ret)

2.3  如果被装饰函数有2个,一个函数有1个参数, 另一个函数有2个参数:

import  time
print(time.time())

def timmer(f):    #装饰器函数
    def inner(*args):
        start = time.time()
        ret = f(*args)       #被装饰的函数
        end = time.time()
        print(end - start)
        return ret
    return inner

@timmer         #语法糖 @装饰器函数名
def func1(a):     #被装饰的函数func1
    time.sleep(0.01)
    print('我好喜欢大家啊',a)
    return '新年好'
# func = timmer(func)
def func2(a,b):     #被装饰的函数func2
    time.sleep(0.01)
    print('我爱大家啊',a,b)
    return '过年好'
# func = timmer(func)
ret = func1(48785)   #inner()
ret = func2(2598,2417)   #inner()
print(ret)

以上只解决了按位置传参数, 但是如果按关键字传参数就会有问题。于是,  可传万能参数

import  time
print(time.time())

def timmer(f):    #装饰器函数
    def inner(*args,**kwargs):
        start = time.time()
        ret = f(*args,**kwargs)       #被装饰的函数
        end = time.time()
        print(end - start)
        return ret
    return inner

@timmer         #语法糖 @装饰器函数名
def func1(a):     #被装饰的函数func1
    time.sleep(0.01)
    print('我好喜欢大家啊',a)
    return '新年好'
# func = timmer(func)
def func2(a,b):     #被装饰的函数func2
    time.sleep(0.01)
    print('我爱大家啊',a,b)
    return '过年好'
# func = timmer(func)
ret = func1(48785)   #inner()
ret = func2(2598,b=2)   #inner()
print(ret)

3. 引出---装饰器的固定格式

def wrapper(f):    #装饰器函数,f是被装饰的函数
    def inner(*args,**kwargs):
        '''在被装饰函数之前要做的事'''
        ret = f(*args,**kwargs)    #被装饰的函数
        '''在被装饰函数之后要做的事'''
        return ret
    return inner
@wrapper         #语法糖 @装饰器函数名
def func(a,b):     #被装饰的函数
    time.sleep(0.01)
    print('我好喜欢大家',a,b)
    return '新年好'
ret = func()  

注意点:

  • func 是被装饰的函数
  • 调用所有被装饰的函数,其实就是调用的inner

 

 单独打印*args,会将参数打散,输出每一个参数。(接收是聚合,调用是打散)

所以以下的例子,inner(*args) 相当于inner(1,2,3,4) 

 

 举例代码:

def wrapper(func):
    def inner(*args,**kwargs):
        print('在被装饰的函数执行之前做的事')
        ret = func(*args,**kwargs)
        print('在被装饰的函数执行之后做的事')
        return ret
    return inner

@wrapper   #holiday = wrapper(holiday)
def holiday(day):
    print('全体放假%s天'%day)
    return '好开心'

ret = holiday(3)
print(ret)

  • 1. 执行def wrapper(func) ,放到内存
  • 2. 执行holiday=wrapper(holiday)的右部分,传给wrapper下面代码
  • 3. 执行def inner(*args,**kwargs)
  • 4. return inner 返回地址
  • 5. 返回地址给holiday , 赋值
  • 6. 执行ret=holiday(3)右部分,  就是相当于inner(3)
  • 7. 执行inner函数,print('在被装饰的函数执行之前做的事')
  • 8. ret = func(*args,**kwargs)  相当于holiday(*(3),**{})
  • 9. 执行函数holiday(3),print('全体放假%s天'%day)
  • 10. return “好开心”   
  • 11. 返回值给ret = func(*args,**kwargs) 的左部分
  • 12. print('在被装饰的函数执行之后做的事')
  • 13. return ret ,拿到返回值“好开心”
  • 14.返回值给holiday=wrapper(holiday)的左部分
  • 15.print(ret)

...

posted on 2019-03-21 16:11  CARLOS_KONG  阅读(444)  评论(0编辑  收藏  举报

导航