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

    函数的闭包

      闭:定义在函数内部的的函数

      包:内部函数用了外部的函数的作用域的名字

    例如:一个简单的例子

    def outter():
        x = 11
        def inner():
            print(x)
        return inner
    res = outter()  #把inner的内存地址赋值给res了
    def func():
        x =333
        res()    #等价于inner()
    func()    #111

    在给函数体传值的时候有两种方式:

    1.传参

    def outter(name):
        print(name)

    2.闭包

    def outter(x,y):
        def inner():
           if x > y:
                return x
              return y
          return inner
    
    res = outter(1,4)
    res()

    介绍了一个模块:

    import requests

    第一个直接给函数传值

    url1 = 'https://www.baiducom'
    def my_get(url1)
        response =requests.get(url1)
        if response.status_code == 200:
            print(len(response.text)
    my_get(url1)

    第二个是闭包的形式传参

    def outter(url):
        def inner():
            response  = requests.get(url)
            if response.status_code == 200:
                print(len(response.text))
        return inner
    
    res = outter('https://www.baidu.com')

    装饰器(*******)

      我们可以把器当成一个工具,装饰就是给对象添加一些别的功能

    为什么要使用装饰器:

      开放封闭的原则:

        开放:对扩展开放

        封闭:对修改封闭

      装饰器要遵循两个原则:

        1.不改变装饰对象的源代码

        2.不改变被装饰的对象

    这只是一个简易的装饰器

    升级版的装饰器

    import time
    def index():
        time.sleep(3)
        print('你好')
        return 'index'
    
    def login():
        time.sleep(1)
        print('您好')
        return 'login'
     
    def outter(func):
        def inner(*args,**kwargs)
        start = time.time()
        res = func(*args,**kwargs)
        return res
        end = time.time()
        print('时间是%s'%(end-start)
        return inner
    index = outter(index)
    login = outter(login)
    index()
    login()    

    装饰器语法糖

    import time
    
    def outter(func):  # func = 最原始的index函数的内存地址
        def get_time(*args, **kwargs):
            start = time.time()
            res = func(*args, **kwargs)  # 最原始的login函数的内存地址() 直接调用  func('egon')
            end = time.time()
            print('func run time:%s'%(end-start))
            return res
        return get_time
    # login = outter(login)  # outter(最原始的login函数的内存地址)
    # index = outter(index)
    # home = outter(home)
    
    @outter  # index = outter(index)  outter(最原始的index的函数的内存地址)
    def index():
        time.sleep(3)
        print('你好')
        return 'index'
    # res1 = index()
    
    
    @outter  # login = outter(login)
    def login(name):
        time.sleep(1)
        print('%s is sb'%name)
        return 'login'
    # res = login('egon')
    
    @outter  # home = outter(home)
    def home(*args,**kwargs):
        time.sleep(1)
        return 'home'
    
    
    # login = outter(login)  # outter(最原始的login函数的内存地址)
    # index = outter(index)
    # home = outter(home)
    
    
    index()
    login('yzy')
    home()

    语法糖的书写要求:

    1.语法糖在书写的时候应该与被装饰对象紧紧挨着

    2.两者之间不能有空格

    对我们来说有一个比较简便的装饰器模板

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

    多层装饰器:

    import time
    
    
    user_dic = {'is_login':None}
    
    
    def outter(func):  # func = 最原始的login函数的内存地址
        def get_time(*args, **kwargs):  # args = ('egon',) kwargs = {}
            start = time.time()
            res = func(*args, **kwargs)  # 最原始的login函数的内存地址() 直接调用  func('egon')
            end = time.time()
            print('func run time:%s'%(end-start))
            return res
        return get_time
    
    def login_auth2(data_source,x,t):
        # data_source = 'file'
        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('please input your username>>>:').strip()
                        password = input('please input your password>>>:').strip()
                        if username == 'jason' and password == '123':
                            user_dic['is_login'] = True
                            res = func(*args,**kwargs)
                            return res
                        else:
                            print('username or password error')
                    elif data_source == 'MySQL':
                        print('from MySQL')
                    elif data_source == 'ldap':
                        print('ldap')
                    else:
                        print('暂无该数据来源')
            return inner
        return login_auth
    
    # 装饰器在装饰的时候  顺序从下往上
    # 装饰器在执行的时候  顺序从上往下
    # res = login_auth2('MySQL')
    @login_auth2('file',1,2) # index = login_auth(get_time)  index = inner函数的内存地址
    # @login_auth
    @outter  # get_time = outter(index)  index是最原始的index
    def index():
        time.sleep(1)
        print('index')
        return 'index'
    index()
    View Code

    装饰器的修复技术

    import time
    
    
    user_dic = {'is_login':None}
    
    
    def outter(func):  # func = 最原始的login函数的内存地址
        def get_time(*args, **kwargs):  # args = ('egon',) kwargs = {}
            start = time.time()
            res = func(*args, **kwargs)  # 最原始的login函数的内存地址() 直接调用  func('egon')
            end = time.time()
            print('func run time:%s'%(end-start))
            return res
        return get_time
    
    def login_auth2(data_source,x,t):
        # data_source = 'file'
        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('please input your username>>>:').strip()
                        password = input('please input your password>>>:').strip()
                        if username == 'jason' and password == '123':
                            user_dic['is_login'] = True
                            res = func(*args,**kwargs)
                            return res
                        else:
                            print('username or password error')
                    elif data_source == 'MySQL':
                        print('from MySQL')
                    elif data_source == 'ldap':
                        print('ldap')
                    else:
                        print('暂无该数据来源')
            return inner
        return login_auth
    
    # 装饰器在装饰的时候  顺序从下往上
    # 装饰器在执行的时候  顺序从上往下
    # res = login_auth2('MySQL')
    @login_auth2('file',1,2) # index = login_auth(get_time)  index = inner函数的内存地址
    # @login_auth
    @outter  # get_time = outter(index)  index是最原始的index
    def index():
        time.sleep(1)
        print('index')
        return 'index'
    index()
    View Code
  • 相关阅读:
    C语言实现二叉堆BuildHeap操作
    Java大浮点数
    线索二叉树
    二叉树的层次遍历
    CS231n Lecture3-Loss Functions and Optimization学习笔记
    Python函数式编程(高阶函数、map/reduce、filter、sorted、匿名函数、返回函数)-3
    CS231n Lecture2-Image Classification学习笔记
    Python高级特性(生成器、迭代器、列表生成式)-2
    Python函数(定义、参数、递归)-1
    Numpy中的广播(Broadcast)讲解简单易懂,困扰已久,终于想通了
  • 原文地址:https://www.cnblogs.com/KrisYzy/p/11171429.html
Copyright © 2011-2022 走看看