python学习笔记 day11 装饰器(二)

语法糖

之前我们使用装饰器时,是为了增加func()函数的功能,有保证func()函数不改变,代码独立性,但是对外还是调用func()函数,然而实现的功能是扩展了之后的,我们是这样做的:

import time
def func():
    print("哈哈哈哈")

def wrapper(f):
    def inner():
        start=time.time()
        time.sleep(0.01)
        f()
        end=time.time()
        print(end-start)
    return inner
func=wrapper(func)
func()

上面的那句func=wrapper(func)其实可以不用写,而是在被装饰函数func()的上面加上@装饰器函数的函数名

import time
def wrapper(f): #装饰器函数
    def inner():
        start=time.time()
        time.sleep(0.01)
        f()
        end=time.time()
        print(end-start)
    return inner

@wrapper  #在被装饰函数的上面(紧挨着)加上@装饰器函数名 效果等同于下面的func=wrapper(func)
def func():  #被装饰的函数
    print("哈哈哈哈")
# func=wrapper(func)
func()

这样就更明显了,直接就好像仍然是调用了func()函数,却好像对原来的func()函数功能进行了扩展;

被装饰的函数func()带有返回值

import time
def wrapper(f):  #装饰器函数参数为被装饰函数的函数名
    def inner():
        start=time.time()
        time.sleep(0.01)
        ret=f()
        end=time.time()
        print(end-start)
        return ret
    return inner

@wrapper
def func():
    return '哈哈哈哈'  #被装饰函数带有返回值

ret=func()  #是有返回值的
print(ret)

程序执行过程:

被装饰函数带有一个参数

import time
def wrapper(f):
    def inner(a):
        start=time.time()
        time.sleep(0.01)
        ret=f(a)
        end=time.time()
        print(end-start)
        return ret
    return inner

@wrapper
def func(a):
    print(a)
    return "哈哈哈哈"

# func=wrapper(func)  #相当于语法糖@wrapper
ret=func(1)
print(ret)

运行结果;

 

但是如果我有很多个函数都需要使用同一个装饰器函数wrapper,但是这些函数参数个数还不一样,这就需要使用之前提到的动态参数啦:

被装饰函数带有*args动态参数(被装饰的函数的参数虽不确定,但都是按照位置传的参数,需要用到动态参数*args)

import time
def wrapper(f):
    def inner(*args):#因为这里的inner其实就是func1,因为func1=wrapper(func1)
        start=time.time()
        time.sleep(0.01)
        ret=f(*args)  #这个f也是func1 因为wrapper(func1) 这个func1就传给了f,而且fcun1是有返回值的,需要有一个变量接收
        end=time.time()
        print(end-start)
        return ret  #inner()函数是需要有返回值的,因为inner就是func1 而func1是有返回值的
    return inner  #wrapper()函数也是有返回值的

@wrapper  #@装饰器函数的函数名,写在被装饰的函数上方(紧挨着)
def func1(a,b):  #该被装饰的函数有两个参数
    print(a,b)
    return "哈哈哈哈"
@wrapper
def func2(c): #该被装饰的函数有一个参数
    print(c)
    return "嘻嘻嘻"
#func1=wrapper(func1)
# func2=wrapper(c=func2)
ret1=func1(1,2)
print(ret1)
ret2=func2(3)
print(ret2)

运行结果:

 如果被装饰的函数参数个数不确定,且可能需要按照位置传参,也有可能是按照关键字传参,这时候需要考虑动态参数 *args 和**kwargs 一起作用!

被装饰函数带有*args,**kwargs动态参数(被装饰的函数的参数不确定,按照位置或者关键字传的参数,需要用到动态参数*args和**kwargs)

import time
def wrapper(f):
    def inner(*args,**kwargs):
        start=time.time()
        time.sleep(0.02)
        ret=f(*args,**kwargs) #因为被装饰的函数是有返回值的
        end=time.time()
        print(end-start)
        return ret  #inner()函数是有返回值的(因为inner=func1 func1()函数有返回值)
    return inner   #装饰器函数返回被装饰的函数名

@wrapper
def func1(a,b,c=1):  #被装饰的函数参数个数不确定,有可能按照位置或者关键字传参
    print(a,b)
    print(c)
    return 'hhhh'  #而且被装饰的函数还有返回值

@wrapper
def func2(a,b,c,d=1,e=2,r=4):
    print(a,b,c)
    print(d,e,r)
    return "xixixi"

# func1=wrapper(func1)  #相当于@wrapper
# func2=wrapper(func2)
ret1=func1(1,2,c=3)
ret2=func2(1,2,3,r=3,d=2,e=6)
print(ret1)
print(ret2)

运行结果::

装饰器函数的固定模板:

def wrapper(f):  #装饰器函数的参数就是被装饰函数的函数名
     def inner(*args,**kwargs):  #该inner就是func 因为语法糖@wrapper=func=wrapper(func) 所以func=inner=f
          """被装饰的函数之前完成的操作"""
          ret=f(*args,**kwargs)  #因为func()被装饰的函数带有返回值
           """被装饰的函数之后完成的操作"""
          return ret  #因为inner=func 而func()函数带有返回值,所以inner()函数也得有返回值
     return inner

@wrapper  #@装饰器函数的函数名,放在被装饰的函数上方
def func(a,b,c=2,f=3,g=4): #被装饰的函数参数个数不确定,按照位置或者关键字传参;
    print("被装饰函数内部各种相关操作")
    return '被装饰的函数带有返回值'

@wrapper
def func2(a,m=2,k=3):  #另一个被装饰的函数,可是位置参数只有一个,关键字参数只有两个,这时候inner(*args,**kwargs)就很有用了
    print('被装饰的函数内部相关操作')
    return "func2函数的返回值"
#func=wrapper(func)  #相当于上面的@wrappper
#func2=wrapper(func2) #@wrapper
func(1,2,c=100,f=300,g=890)  #按照关键字传参时,名字得对应啦!!
func2(1,m=100,k=300)
talk is cheap,show me the code
原文地址:https://www.cnblogs.com/xuanxuanlove/p/9563163.html