zoukankan      html  css  js  c++  java
  • 闭包函数与装饰器

    今日内容


     

    闭包函数:


     

    • 1.闭:定义在函数内部的函数
    • 2.包:内部函数引用了外部函数作用域的名字
    def outter():
    
        x = 1
    
        def inner()
    
            print(x)   # 这一步引用 x = 1
    
        return inner
    
    res = outter()
    
    res()  # 1 
    
    def func()
    
        x = 2
    
       res()  # 这里相当于 res(outter()),而res()的调用结果为1
    
    func()  #  1 ,这里调用func函数,执行内部函数代码,虽然x = 2存在,但是执行res()后,又执行了一次x = 1赋值,所以结果返回1  
    • 给函数体传值的第一种方式:传参
    def index(username):
    
        print(username)
    • 给函数体传值的第二种方式:闭包
    def outter()
    
        x = 1
    
        y = 2
    
        def my_max():
    
            if x > y:
    
                return x
    
            return y
    
        return my_max
    
    res = outter()  # res 就是my_max函数的内存地址
    
    res()  # my_max函数的内存地址
    
    print(res())  #结果为x,y中的最大值 
    闭包方式1

    或者

    def outter(x,y)
    
        def my_max():
    
            if x > y:
    
                return x
    
            return y
    
        return my_max
    
    res = outter(1,2)  # res 就是my_max函数的内存地址
    
    res()  #  my_max函数的内存地址
    
    print(res())  # x,y中的最大值
    闭包方式2

    Pycharm解释器知识点: pip3 install requests装requests模块

    • 函数传参的第一种方式:直接给函数传参
    import requests   # 导入requests模块
    
    def my_get(url):
    
        response = requests.get(url)
    
        if response.status_code == 200:
    
            print(len(response.text))
    
    my_get('此处输入网址')    
    直接给函数传参
    • 函数传参的第二种方式:*闭包*
    import requests
    
    def outer()
    
        url = '网址'
    
        def my_get():
    
            response = requests.get(url)
    
            if response.status_code == 200:
    
                print(len(response.text))
    
        return my_get()
    
    my_jd = outter('此处输入网址')
    
    my_jd()   # 相当于my_jd(outter())
    
    my_baidu = outter('此处输入网址')
    
    my_baidu()   # 相当于my_baidu(outter())

     

    装饰器:


     

    装饰器:用工具给被装饰对象添加新的功能

    开放封闭原则:

    • 开放:对扩张开放 (你扩展没事,别减少代码)
    • 封闭:对修改封闭 (不被允许修改原代码被修饰函数代码)

    装饰器必须遵循的两个原则:

    • 1.不改变被装饰对象源代码
    • 2.不改变被装饰对象(可调用对象)的调用方式
    def index():
    
        pass
    
    index()   # 上面定义的index函数,你就老老实实的用常规方式调用index()函数

    关于如何使用?

    • 1.统计index函数执行时间
    import time
    
    print(time.time(3))  # 1562812014.731474 时间戳,当前时间距离1970-1-1 00:00:00相差的秒数
    
    def index():
    
        print('XXXXXX')
    
    time.sleep(3)  # 此处是让cpu睡3秒
    
    print('XXXXX')  # 这是返回输出XXXXX所执行的时间
    • 2.下面是常规的用start和end来记录当前时间:
    import time
    
    def index():
    
        time.sleep(3)
    
        print('XXXXXX')
    
    strat = time.time()
    
    index()
    
    end = time.time()
    
    print('index run time:%s'%(end-start))   # 返回的是index函数从开始到结束的运行时间差
    • 3.下面是初步装饰函数:
    import time
    
    def index():
    
        time.sleep(3)
    
        print('XXXXXX')
    
    def get_time(func)  # func=index函数
    
        strat = time.time()
    
        func()  # func=index函数内存地址()
    
        end = time.time()
    
        print('index run time:%s'%(end-start))
    
    get_time(index)

    装饰器简单版本:

    import time
    
    def index():
    
        time.sleep(3)
    
        print('XXXXXX')
    
    def outter(func):
    
        def get_time():
    
            start = time.time()
    
            func()
    
            end = time.time()
    
            print('index run time:%s' % (end - start))
    
        return get_time
    
    res = outter(index)
    
    res()
    简单版本

    装饰器进化版本:

    如果我们要统计login执行时间:

    import time
    
    def index():
    
        time.sleep(3)
    
        print('XXXXXX')
    
    
    def login(name):
    
        time.sleep(1)
    
        print('%s is sb'%name)
    
    
    def outter(func):  # func = 最开始的login函数的内存地址
    
        def get_time(*args,**kwargs):  # args = ('egon',) kwargs = {} 
    
            strat = time.time()
    
            func(*args,**kwargs)  # func=最开始的login函数内存地址() 直接调用
    
            end = time.time()
    
            print('index run time:%s'%(end-start))
    
        return get_time
    
    login = outter(login)  # outer(最开始的login函数内存地址) 
    
    login('egon')        
    View Code
    import time
    
    def index():
    
        time.sleep(3)
    
        print('XXXXXX')
    
    
    def login(name):
    
        time.sleep(1)
    
        print('%s is sb'%name)
    
    
    def outter(func):  # func = 最开始的login函数的内存地址 
    
        def get_time(*args,**kwargs):  # args = ('egon',) kwargs = {} 
    
           strat = time.time()
    
            res = func(*args,**kwargs)  # func=最开始的login函数内存地址() 直接调用
    
            return res
    
            end = time.time()
    
            print('index run time:%s'%(end-start))
    
        return get_time
    
    login = outter(login)  # outer(最开始的login函数内存地址)
    
    res = login('egon')
    
    login('egon')    
    View Code2

    ''''''

    函数参数的问题:无参函数和有参函数是否都可以直接调用

    函数可以接收任意数量的参数

    语法糖在书写时应该与被装饰对象紧挨着,两者之间不要有空格

    '''''' 

    def outter(func):
    
        def get_time(*args,**kwargs):
    
            strat = time.time()
    
            func(*args,**kwargs)
    
            return res
    
            end = time.time()
    
            print('index run time:%s'%(end-start))
    
        return get_time
    
     
    @outter  # login = outer(index)
    
    def index():
    
        time.sleep(3)
    
        print('XXXXXX')
    
     
    @outter  # login = outer(login)
    
    def login(name):
    
        time.sleep(1)
    
        print('%s is sb'%name)
    语法糖的应用

    装饰器模板:

    def outter(func):
    
        def inner(*args,**kwargs):
    
            print('执行被装饰函数之前,你可以做的操作')
    
            res = func(*args,**kwargs)
    
            print('执行被装饰函数之后,你可以做的操作')
    
            return res
    
        return inner

    认证装饰器:

    执行函数index之前必须先输入用户名和密码,正确之后才能执行index;否则提示用户输入错误,结束程序

    import time
    
        user_dic = {'is_login':None}
    
        def login_auth(func):  # 其实就是func = index
    
            def inner(*args,**kwargs):
    
                if user_dic['is_login']:
    
                    res = func(*args,**kwargs)
    
                    return res
    
                else:
    
                    username = input('请输入用户名:').strip()
    
                    password = input('请输入密码:').strip()
    
                    if username == 'jason' and password == '123':
    
                        user_dic['is_login'] = True
    
                        res = func(*args,**kwargs)
    
                        return res
    
                    else:
    
                        print('用户名或者密码错误')
    
            return inner
    
     
    @login_auth
    
    def index(name):
    
        time.sleep(1)
    
        print('%s is dsb'%name)    
    认证装饰器

    多层装饰器:(重要)


    装饰器在装饰的时候,顺序是从下往上

    装饰器在执行的时候,顺序是从上往下

    import time
    
    
    def outter(func):
    
        def get_time(*args,**kwargs):
    
            strat = time.time()
    
            res = func(*args,**kwargs)
    
            return res
    
            end = time.time()
    
            print('index run time:%s'%(end-start))
    
        return get_time
    
    
    def login_auth(func):  # 其实就是func = index
    
        def inner(*args,**kwargs):  # 这里的参数是跟被装饰函数的参数一一对应的
    
            if user_dic['is_login']:
    
                res = func(*args,**kwargs)
    
                return res
    
            else:
    
                username = input('请输入用户名:').strip()
    
                password = input('请输入密码:').strip()
    
                if username == 'jason' and password == '123':
    
                    user_dic['is_login'] = True
    
                    res = func(*args,**kwargs)
    
                    return res
    
                else:
    
                    print('用户名或者密码错误')
    
        return inner
    
     
    @login_auth  # index = login_auth(get_time) index = inner函数的内存地址
    
    @outter  # get_time = outter(index) index是最开始的index
    
    def index(name):
    
        time.sleep(1)
    
        print('%s is dsb'%name)    
    多层装饰器

    三层装饰器:(重要)


     

    def login_auth2(data_source)
    
        def login_auth(func):  # 其实就是func = index
    
            def inner(*args,**kwargs):  # 这里的参数是跟被装饰函数的参数一一对应的
    
               if user_dic['is_login']:
    
                    res = func(*args,**kwargs)
    
                    return res
    
                else:
    
                    if data_source == 'file':
    
                        username = input('请输入用户名:').strip()
    
                        password = input('请输入密码:').strip()
    
                        if username == 'jason' and password == '123':
    
                            user_dic['is_login'] = True
    
                            res = func(*args,**kwargs)
    
                            return res
    
                        else:
    
                            print('用户名或者密码错误')
    
                    elif data_source == 'MYSQL':
    
                        print('form MYSQL')
    
                    elif data_source == 'ldsp':
    
                        print('from ldsp')
    
                    else:
    
                        print('暂时无数据来源')
    
            return inner
    
     
    @login_auth2(data_source,x,t)  # login_auth2(data_source,x,t)等价于login_auth,data_source = 'file' 
    
    @outter  # get_time = outter(index) index是最开始的index
    
    def index(name):
    
        time.sleep(1)
    
        print('%s is dsb'%name)                
    三层装饰器

    装饰器补充:

    我们用装饰器的最终目标就是:

    • 用户查看被装饰函数的函数名的时候,查看到的就是被装饰函数本身
    • 用户查看被装饰函数的注释的时候,查看到的就是被装饰函数的注释

    方法就是下面这两句代码:

    form functools import wraps

    @wraps(func) '''装饰器修复技术'''

    form functools import wraps
    
    def outter(func):
    
        @wraps(func)  # 装饰器修复技术
    
        def inner(*args,**kwargs):
    
            print('执行被装饰函数之前,你可以做的操作')
    
            res = func(*args,**kwargs)
    
            print('执行被装饰函数之后,你可以做的操作')
    
            return res
    
        return inner
    
     
    @outter  # outter(最原始的index内存地址)
    
    def index():
    '''
    这是index函数
    :return
    '''
    print(index)
    
    print(help(index))  # 查看函数的注释
    
    print(index.name)  # 查看函数名字字符串形式
    装饰器补充

     

  • 相关阅读:
    java 支付宝即时到帐提交订单dome
    C#字符串string的常用使用方法(转载)
    UltraEdit 回车符替换空格
    java 七牛上传图片到服务器(采用的html5 压缩 传输base64方式)
    c# 多播委托
    c# 泛型委托
    c# 求数组的最大值
    c# 匿名函数和lamda表达式语法
    匿名函数和lamda表达式
    导出Excel之Epplus使用教程4(其他设置)
  • 原文地址:https://www.cnblogs.com/zhukaijian/p/11179233.html
Copyright © 2011-2022 走看看