• Python函数装饰器


    装饰器的原则

    1)不修改被修饰函数的源代码;

    2)不修改被修饰函数的调用方式;

    装饰器的知识点 = 高阶函数 + 函数嵌套 + 闭包

    1. 只用高阶函数写装饰器--->有瑕疵

    import time
    
    def foo():
        print('this is foo')
        # return foo
    
    def timer(func):
        starttime = time.time()
        func()
        stoptime = time.time()
        print('使用的时间是:%s' %(stoptime - starttime))
        return func
    
    foo = timer(foo)
    foo()
    
    #执行结果是:
    # this is foo
    # 使用的时间是:0.00013685226440429688
    # this is foo            #多了一次执行结果

    2. 闭包其实就是函数的嵌套

    def First(name):
        print('FirstLayer:%s' %name)
        def Second():
            name = 'bbb'
            print('SecondLayer:%s' %name)
            def Third():
                name = 'ccc'
                print('ThirdLayer:%s' %name)
            Third()
        Second()
    First('aaa')

    3. 函数闭包装饰器基本实现

    # 实现阶段1:只需要在原来函数调用之前进行赋值操作。
    import  time
    
    def timer(func):   #func == test
        def good():
            starttime = time.time()
            func()
            stoptime = time.time()
            print('程序消耗的时间是:%s' %(stoptime - starttime))
        return good
    
    def test():
        print('这是test函数')
    
    test = timer(test)      #此处函数运行的结果是return的good,可以看下一步证实。
    print(timer(test))      #<function timer.<locals>.good at 0x10e3cb700>,因此需要下一步运行返回值函数good。
    test()                  #test = good
    # 实现阶段2:通过语法糖改进后,完全不需要动原来函数;
    import time
    
    def timer(func):   #func == test
        def good():
            starttime = time.time()
            func()
            stoptime = time.time()
            print('程序消耗的时间是:%s' %(stoptime - starttime))
        return good
    
    @timer  #@timer  相当于 test = timer(test)
    
    def test():
        print('这是test函数')
    test()
    # 实现阶段3:如何打印出真正test的返回值
    import time
    
    def timer(func):   #func == test
        def good():
            starttime = time.time()
            res = func()            #就是在运行test()
            stoptime = time.time()
            print('程序消耗的时间是:%s' %(stoptime - starttime))
            return res
        return good
    
    @timer  #@timer  相当于 test = timer(test)
    
    def test():
        print('这是test函数')
        return '这是test的返回值'
    ras = test()
    print(ras)
    # 阶段4装饰器适用于不同参数个数的函数
    import time
    
    def timer(func):   #func == test
        def good(*args,**kwargs):
            starttime = time.time()
            res = func(*args,**kwargs)            #就是在运行test()
            stoptime = time.time()
            print('程序消耗的时间是:%s' %(stoptime - starttime))
            return res
        return good
    
    @timer  #@timer  相当于 test = timer(test)
    
    def test(name,age,gender):
        print('这是test函数,名字是%s,年龄是%s,性别是%s' %(name,age,gender))
        return '这是test的返回值'
    ras = test('aaa','18','male')
    print(ras)
    
    @timer   #@timer  相当于 test1 = timer(test1)
    def test1(name,age,gender,hight):
        print('这是test1函数,,名字是%s,年龄是%s,性别是%s,身高是%s' %(name,age,gender,hight))
        return '这是test1的返回值'
    ras = test1('bbb','20','male','175')
    print(ras)
    
    # 如下为返回结果:
    # 这是test函数,名字是aaa,年龄是18,性别是male
    # 程序消耗的时间是:8.0108642578125e-05
    # 这是test的返回值
    # 这是test1函数,,名字是bbb,年龄是20,性别是male,身高是175
    # 程序消耗的时间是:1.0013580322265625e-05
    # 这是test1的返回值

    4. 解压序列补充

    # 使用解压序列取列表中的最开头和最结尾的值,可灵活使用。
    >>> l = [1,2,3,4,5,6]
    >>> a,*_,b = l
    >>> l
    [1, 2, 3, 4, 5, 6]
    >>> a
    1
    >>> b
    6
    >>> a,*b,c = l
    >>> a
    1
    >>> b
    [2, 3, 4, 5]
    >>> c
    6
    #快速交换两个变量的值
    >>> f1,f2 = 1,2
    >>> f1
    1
    >>> f2
    2
    >>> f1,f2 = f2,f1
    >>> f1
    2
    >>> f2
    1

    5. 终极版装饰器-带参数验证功能的装饰器

    user_list=[
        {'name':'alex','passwd':'123'},
        {'name':'linhaifeng','passwd':'123'},
        {'name':'wupeiqi','passwd':'123'},
        {'name':'yuanhao','passwd':'123'},
    ]
    current_dic={'username':None,'login':False}
    
    def auth(auth_type='filedb'):
        def auth_func(func):
            def wrapper(*args,**kwargs):
                print('认证类型是',auth_type)
                if auth_type == 'filedb':
                    if current_dic['username'] and current_dic['login']:
                        res = func(*args, **kwargs)
                        return res
                    username=input('用户名:').strip()
                    passwd=input('密码:').strip()
                    for user_dic in user_list:
                        if username == user_dic['name'] and passwd == user_dic['passwd']:
                            current_dic['username']=username
                            current_dic['login']=True
                            res = func(*args, **kwargs)
                            return res
                    else:
                        print('用户名或者密码错误')
                elif auth_type == 'ldap':
                    print('鬼才特么会玩')
                    res = func(*args, **kwargs)
                    return res
                else:
                    print('鬼才知道你用的什么认证方式')
                    res = func(*args, **kwargs)
                    return res
    
            return wrapper
        return auth_func
    
    @auth(auth_type='filedb') #auth_func=auth(auth_type='filedb')-->@auth_func 附加了一个auth_type  --->index=auth_func(index)
    def index():
        print('欢迎来到京东主页')
    
    @auth(auth_type='ldap')
    def home(name):
        print('欢迎回家%s' %name)
    #
    @auth(auth_type='sssssss')
    def shopping_car(name):
        print('%s的购物车里有[%s,%s,%s]' %(name,'奶茶','妹妹','娃娃'))
    
    # print('before-->',current_dic)
    # index()
    # print('after--->',current_dic)
    # home('产品经理')
    shopping_car('产品经理')
  • 相关阅读:
    pyinstaller安装和使用
    django项目结构和运行项目
    安装django and 创建项目
    浅谈网络请求基础(理论篇)
    浅谈爬虫初识
    判断是否AVL平衡二叉书
    用递归方法判断两棵树是否相等
    广度优先搜索求树的深度
    堆排序
    归并排序
  • 原文地址:https://www.cnblogs.com/wangzengyi/p/12303018.html
Copyright © 2020-2023  润新知