zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    JSON获取地址
    Java的selenium代码随笔(8)
    Java的selenium代码随笔(7)
    Java的selenium代码随笔(6)
    MySql插入点数据
    Win7系统用户文件夹多出一个Administrator.xxx开头的文件怎么解决
    Android Studio导入第三方类库的方法
    转:eclipse 设置Java快捷键补全
    解决android studio引用远程仓库下载慢(JCenter下载慢)
    AndroidStudio下载地址
  • 原文地址:https://www.cnblogs.com/xuanxuanlove/p/9563163.html
Copyright © 2011-2022 走看看