zoukankan      html  css  js  c++  java
  • 装饰器

    装饰器

      一、装饰器定义:本质就是函数,功能是为其它函数添加附加功能

    原则:
    1、不修改被修饰函数的源代码
    2、不修改被修饰函数的调用方式
    装饰器的知识储备
    装饰器=高阶函数+函数嵌套+闭包


    二、高阶函数
    高阶函数定义:
    1、函数接受的参数是一个函数名
    2、函数的返回值是一个函数名
    3、满足上述条件任意一个,都称为高阶函数
    def foo():
        print('您好啊赵师傅')  #4、打印
        return foo  #5、return 
    
    def test(func):  #2、接受foo参数,代入函数体
        func()    #3、执行foo函数
    
    test(foo) #1、执行test函数,传参foo
    
    执行结果:
    您好啊赵师傅
    
    

    三、在遵循装饰器原则的基础上,修改上述代码,增加计时功能;

    ps1:

    import time
    #满足条件1:作用是,可以在不修改源代码的情况下,为被修改函数foo添加新功能
    #问题是,修改了foo的调用方式
    def foo():
      time.sleep(2)
    print('您好啊赵师傅') def test(func): start_time = time.time()  #计算开始时间 func()  #执行foo函数 stop_time = time.time()  #计算结束时间 print('执行函数所用时间:【%s】'%(stop_time-start_time))  #结束时间减去开始时间为运行时间 test(foo)

    执行结果:
    您好啊赵师傅
    执行函数所用时间:【2.0001139640808105】

    ps2:

    #满足条件:
    #1、不修改foo源代码
    #2、不修改foo调用方式
    #但是多调用一次,不满足业务需求
    def foo():  
        print('您好啊赵师傅')  #3、调用函数打印信息
    
    def test(func):
        start_time = time.time()
        func()    #2、执行传入的foo函数
        stop_time = time.time()    
        print('执行函数所用时间:【%s】'%(stop_time-start_time))   #4、打印时间
        return func #返回foo函数值
    foo=test(foo)  #1、执行函数test(foo),并把foo传入函数体/ #6、foo变量接受return的foo()函数的内存地址
    foo()  #7、得到内存地址,再次执行了一遍foo函数
    
    执行结果:
    您好啊赵师傅
    执行函数所用时间:【0.0】
    您好啊赵师傅

    四、函数嵌套、闭包概念

    函数嵌套定义:函数内部再定义函数
    闭包概念:封装内层的变量值(函数也是变量)
    ps1:
    def father(name):
        def son():
            print('我的父亲是%s'%name) #3、打印
            def grandson():
                print('我的爷爷是%s'%name) #5、打印
            grandson()  #4、调用grandson()
        son() #2、调用son()
    
    father('zk') #1、调用father函数,传参zk给函数体
    
    执行结果:
    我的父亲是zk
    我的爷爷是zk

    五、装饰器基本架子

    ps1:基础架子

    def timer(func):  
        def wrapper():
            func()  
        return wrapper

    ps2:加上参数

    def timer(func):
        def wrapper(*args,**kwargs):  #接受实际函数所传的参数,给wrapper函数内部调用
            func(*args,**kwargs)  #将参数
        return wrapper

    ps3:加上功能

    import time
    def timer(func):
        def wrapper(*args,**kwargs):
            start_time=time.time()  #可加上具体功能
            func(*args,**kwargs)   #func为外层变量,在内层可以获取到
            stop_time=time.time()
            print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time))
        return wrapper

    ps4:加上返回值

    import time
    def timer(func):
        def wrapper(*args,**kwargs):
            start_time=time.time()
            res=func(*args,**kwargs)  #返回实际执行函数的返回值,用个变量接收到
            stop_time=time.time()
            print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time))
            return res  #在返回得到的变量的值,这时wrapper的返回值,就是实际执行函数的返回值了
        return wrapper

    装饰器调用解析:

    ps1:

    def timer(func):  #func————>test
        def wrapper():
            func()  #就是在运行test函数
        return wrapper
    
    
    #———————————————以上部分是基本架子—————————————————————
    
    def test():
        print('test执行完毕')
    
    res=timer(test) #返回的是wrapper的内存地址    用res接收wrapper的内存地址
    res()  #执行的是wrapper函数

    语法糖@

    @timer  #@timer就等同于res=timer(test)   后两句
    def timer(func):  #func————>test
        def wrapper():
            func()  #就是在运行test函数
        return wrapper
    def test():
        print('test执行完毕')
    
    #res=timer(test) #返回的是wrapper的内存地址    用res接收wrapper的内存地址
    #res()  #执行的是wrapper函数

    无参数装饰器实例

    user_list=[
        {'name':'alex','passwd':'123'},
        {'name':'linhaifeng','passwd':'123'},
        {'name':'wupeiqi','passwd':'123'},
        {'name':'yuanhao','passwd':'123'},
    ]
    
    current_user={'username':None,'login':False}
    
    def auth_deco(func):
        def wrapper(*args,**kwargs):
            if current_user['username'] and current_user['login']:
                res=func(*args,**kwargs)
                return res
            username=input('用户名: ').strip()
            passwd=input('密码: ').strip()
    
            for index,user_dic in enumerate(user_list):
                if username == user_dic['name'] and passwd == user_dic['passwd']:
                    current_user['username']=username
    
                    current_user['login']=True
                    res=func(*args,**kwargs)
                    return res
                    break
            else:
                print('用户名或者密码错误,重新登录')
    
        return wrapper
    
    @auth_deco
    def index():
        print('欢迎来到主页面')
    
    @auth_deco
    def home():
        print('这里是你家')
    
    def shopping_car():
        print('查看购物车啊亲')
    
    def order():
        print('查看订单啊亲')
    
    print(user_list)
    # index()
    print(user_list)
    home()
    
    无参装饰器

    带参数装饰器实例

    user_list=[
        {'name':'alex','passwd':'123'},
        {'name':'linhaifeng','passwd':'123'},
        {'name':'wupeiqi','passwd':'123'},
        {'name':'yuanhao','passwd':'123'},
    ]
    
    current_user={'username':None,'login':False}
    def auth(auth_type='file'):
        def auth_deco(func):
            def wrapper(*args,**kwargs):
                if auth_type == 'file':
                    if current_user['username'] and current_user['login']:
                        res=func(*args,**kwargs)
                        return res
                    username=input('用户名: ').strip()
                    passwd=input('密码: ').strip()
    
                    for index,user_dic in enumerate(user_list):
                        if username == user_dic['name'] and passwd == user_dic['passwd']:
                            current_user['username']=username
                            current_user['login']=True
                            res=func(*args,**kwargs)
                            return res
                            break
                    else:
                        print('用户名或者密码错误,重新登录')
                elif auth_type == 'ldap':
                    print('ldap___模式')
                    res=func(*args,**kwargs)
                    return res
            return wrapper
        return auth_deco
    
    
    #auth(auth_type='file')就是在运行一个函数,然后返回auth_deco,所以@auth(auth_type='file')
    #就相当于@auth_deco,只不过现在,我们的auth_deco作为一个闭包的应用,外层的包auth给它留了一个auth_type='file'参数
    @auth(auth_type='ldap')
    def index():
        print('欢迎来到主页面')
    
    @auth(auth_type='ldap')
    def home():
        print('这里是你家')
    
    def shopping_car():
        print('查看购物车啊亲')
    
    def order():
        print('查看订单啊亲')
    
    # print(user_list)
    index()
    # print(user_list)
    home()
    
    带参装饰器

     自己写的练习题:

    user_list=[
        {'user':'','passwd':'111111'},
        {'user':'','passwd':'111111'}
    ]
    
    operating_dic={'user_name':None,'login_zt':False}
    def jd_date(my_db='mysql'):
        def jd_yz(func):
            def wrapper(*arg,**kwargs):
                if my_db=='mysql':
                    if operating_dic['user_name'] and operating_dic['login_zt']:
                        print(operating_dic)
                        res=func(*arg,**kwargs)
                        return res
                    else:
                        user=str(input('用户名:'))
                        passwd=str(input('密码:'))
                        for i in user_list:
                            if user==i['user'] and passwd==i['passwd']:
                                operating_dic['user_name']=user
                                operating_dic['login_zt']=True
                                res=func(*arg,**kwargs)
                                return res
                        else:
                            print('用户名密码错误!!!')
                elif my_db =='sql_server':
                    print('使用sql_server数据库验证')
                else:
                    print('谁知道你用的是鸟验证')
            return wrapper
        return jd_yz
    @jd_date(my_db='mysql')
    def index(name):
        print('欢迎%s来到京东'%(name))
    
    @jd_date(my_db='sql_server')
    def home(name):
        print('欢迎%s回家'%(name))
    
    @jd_date(my_db='abc')
    def order(name):
        print('%s的订单'%(name))
    
    index('zk')
    home('zk')
    order('zk')
  • 相关阅读:
    XMPP框架下微信项目总结(5)花名册获取(好友列表)
    XMPP框架下微信项目总结(4)重新连接服务器
    XMPP框架下微信项目总结(3)获取点子名片信息(个人资料)更新电子名片
    XMPP框架下微信项目总结(2)授权登陆/注销/注册/打印日志
    XMPP框架下微信项目总结(1)环境配置
    比较 http连接 vs socket连接
    js判断变量是否为undefined
    sql查询优化的方法
    Jquery学习之插件开发
    Jquery学习之Jquery插件
  • 原文地址:https://www.cnblogs.com/shangpolu/p/6143162.html
Copyright © 2011-2022 走看看