zoukankan      html  css  js  c++  java
  • 20.装饰器和函数闭包

    原文:https://www.cnblogs.com/linhaifeng/articles/6140395.html

    1.装饰器

    器即函数

    装饰即修饰,意指为其他函数添加新功能

    装饰器定义:本质就是函数,功能是为其他函数添加新功能

    2.装饰器原则

    1.不修改被装饰函数的源代码(开放封闭原则)

    2.为被装饰函数添加新功能后,不修改被修饰函数的调用方式

    3.实现装饰器需要哪些知识

    装饰器=高阶函数+函数嵌套+闭包

    4.高阶函数

    高阶函数定义:
    1.函数接收的参数是一个函数名

    2.函数的返回值是一个函数名

    3.满足上述条件任意一个,都可称之为高阶函数

    import time
    def foo():
        time.sleep(3)
        print('来自foo')
    
    #不修改foo源代码
    #不修改foo调用方式
    
    
    #多运行了一次,不合格
    # def timer(func):
    #     start_time=time.time()
    #     func()
    #     stop_time = time.time()
    #     print('函数运行时间是  %s' % (stop_time-start_time))
    #     return func
    # foo=timer(foo)
    # foo()
    
    
    #没有修改被修饰函数的源代码,也没有修改被修饰函数的调用方式,但是也没有为被修饰函数添加新功能
    def timer(func):
        start_time=time.time()
        return func
        stop_time = time.time()
        print('函数运行时间是  %s' % (stop_time-start_time))
    
    foo=timer(foo)
    foo()

    5.函数嵌套

    指在一个函数里又定义了一个函数

    def father(name):
        print('from father %s' %name)
        def son():
            print('from son')
            def grandson():
                print('from grandson')
            grandson()
        son()
    father('ray')

    6.闭包

    闭包:在一个作用域里放入定义变量,相当于打了一个包。ps:一个作用域的范围就是一个函数。

     

     7.装饰器例子

    无参装饰器=高级函数+函数嵌套

    语法糖@,调用装饰器

    基本实现

    import time
    def timmer(func): #func=test
        def wrapper():
            # print(func)
            start_time=time.time()
            func() #就是在运行test()
            stop_time = time.time()
            print('运行时间是%s' %(stop_time-start_time))
        return wrapper
    
    @timmer #test=timmer(test)
    def test():
        time.sleep(3)
        print('test函数运行完毕')
    test()
    
    # res=timmer(test)  #返回的是wrapper的地址
    # res()  #执行的是wrapper()
    
    # test=timmer(test)  #返回的是wrapper的地址
    # test()  #执行的是wrapper()
    
    #  @timmer  就相当于 test=timmer(test)

    加返回值(res = func())

    import time
    def timmer(func): #func=test
        def wrapper():
            start_time=time.time()
            res=func() #就是在运行test()
            stop_time = time.time()
            print('运行时间是%s' %(stop_time-start_time))
            return res
        return wrapper
    
    @timmer #test=timmer(test)
    def test():
        time.sleep(3)
        print('test函数运行完毕')
        return '这是test的返回值'
    
    res=test()  #就是在运行wrapper
    print(res)

    加参数

    import time
    def timmer(func): #func=test1
        def wrapper(*args,**kwargs): #test('linhaifeng',age=18)  args=('linhaifeng')  kwargs={'age':18}
            start_time=time.time()
            res=func(*args,**kwargs) #就是在运行test()         func(*('linhaifeng'),**{'age':18})
            stop_time = time.time()
            print('运行时间是%s' %(stop_time-start_time))
            return res
        return wrapper
    
    # @timmer #test=timmer(test)
    def test(name,age):
        time.sleep(3)
        print('test函数运行完毕,名字是【%s】 年龄是【%s】' %(name,age))
        return '这是test的返回值'
    
    @timmer
    def test1(name,age,gender):
        time.sleep(1)
        print('test1函数运行完毕,名字是【%s】 年龄是【%s】 性别【%s】' %(name,age,gender))
        return '这是test的返回值'
    
    # res=test('linhaifeng',age=18)  #就是在运行wrapper
    # # print(res)
    # test1('alex',18,'male')
    
    test1('alex',18,'male')

    8.模拟网站登录例子(带参数验证功能装饰器)

    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('产品经理')

    9.解压序列

    例:a,*_,c = x  ,a是开头值,c是结尾值,下划线是中间的值。等同于x[0],x[-1].

    两个效果一样,下面的更方便。

     

     

     

     

     

     

     
  • 相关阅读:
    Python数组/切片
    ArcGISEngine 版本升级的方法
    c# 使用类名称访问成员变量
    向模拟器里添加图片的简单方法
    通过self调用propery和直接调用propery的区别
    Objectivec 使用构造函数来初始化函数并调用函数的方法
    IPhone模拟器截取当前活动窗体,并保存为图片
    Windows Server2008 安装Oracle失败
    ALL、DISTINCT、DISTINCTROW、TOP 谓词
    ObjectiveC 语法快速参考
  • 原文地址:https://www.cnblogs.com/raitorei/p/11958549.html
Copyright © 2011-2022 走看看