• 闭包函数、装饰器


    一、补充知识点

    1、可调用的callable(可以加括号执行某个特定功能):函数名,类名

    2、import this:查看Python之禅

    二、闭包函数

    1、定义

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

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

    2、形式

    def outter(x,y):
        def inner():
            代码1
            代码2
        return inner
     
    res = outter(1, 2)
    res()

    3、作用

      给函数体传参有两种方式,第一种是直接给函数体传参,第二种就是用闭包函数,它是利用外部函数给内部函数传参,这样在调用内部函数的时候,就可以不写参数。

    4、举例

    import requests  # requests是python实现的简单易用的HTTP库
    def outter(url):
        def my_get():
            response = requests.get(url)
            if response.status.code == 200:
                print(len(response.text))
            return my_get
    my_jd = outter("https://www.jd.com")
    my_jd()

    三、装饰器

    1、定义

      器:就是一个工具

      装饰:给被装饰对象添加新的功能

    2、开放封闭原则

      开放:对扩展开放

      封闭:对修改封闭

    3、装饰器必须遵守的两个原则

      ①、不改变被装饰对象源代码

      ②、不改变被装饰对象(可调用对象)调用方式

    4、装饰器简单版

    """
    统计index函数执行的时间
    """
    import time  # 导入时间模块
    def index():
        time.sleep(1)
    #让程序暂停1秒,测量程序运行时间时,如果时间过短,测量时间会是0,加上延时后就可以测量
        print('澳门最大线上赌场开业啦 性感tank在线发牌!')
    
    def outter(func):  # func = 最原始的index函数的内存地址
        def get_time():
            start = time.time()
            func()  # func = index函数的内存地址() 直接调用
            end = time.time()
            print('index run time:%s'%(end-start))
        return get_time
    index = outter(index)  # outter(最原始的index函数内存地址)
    # index指向get_time函数的内存地址
    index()
    

    5、装饰器升级版

    解决了函数参数的问题,无参函数和有参函数都可以直接调用,可以接收任意数量的参数

    import time
    def index():
        time.sleep(1)
        print('from index')
        return index
    res = index()  # from index
    
    def login(name):
        time.sleep(1)
        print(name)
        return login
    res1 = login('egon')  # egon
    
    def outter(func):
        def get_time(*args, **kwargs):
    # 可以传入任意参数,放入元组和字典中
            start = time.time()
            res = func(*args, **kwargs)
    # 将元组和字典打散,将参数原封不动的传给func函数
            end = time.time()
            print(end-start)
            return res
        return get_time
    
    index = outter(index)  
    login = outter(login)
    index()
    # from index
    # 1.0002615451812744
    # 此时的index()已经多了计时功能
    login('egon')
    # egon
    # 1.0002918243408203
    # 此时的login()已经多了计时功能
    print(res)
    # <function index at 0x00DFA660>
    print(res1)
    # <function login at 0x028435D0>
    print(index)
    # <function outter.<locals>.get_time at 0x028436F0>
    print(login)
    # <function outter.<locals>.get_time at 0x02843660>
    

    6、装饰器语法糖

      ①、形式

    import time
    
    
    def outter(func):
        def get_time(*args, **kwargs):
            start = time.time()
            res = func(*args, **kwargs)
            end = time.time()
            print('func run time:%s'%(end - start))
            return res
        return get_time
    
    
    @outter
    def index():
        time.sleep(1)
        print('澳门最大线上赌场开业了!')
        return 'index'
    
    
    @outter
    def login(name):
        time.sleep(1)
        print('%s is sb'%name)
        return 'login'
    
    
    @outter
    def home(*args, **kwargs):
        time.sleep(1)
        return 'home'
    
    
    res = index()
    res1 = login('egon')
    res2 = home()
    print(res, res1, res2)
    
    
    # 输出
    澳门最大线上赌场开业了!
    func run time:1.0009095668792725
    egon is sb
    func run time:1.0010344982147217
    func run time:1.0009922981262207
    index login home
    

      ②、作用

      书写代码的时候省去了login = outter(login),index = outter(index),home = outter(home)这三行代码,因为@outter自动帮你做了这件事,它会将下面最靠近它的函数的函数名当做参数传入outter()函数,并将返回值(内部函数的函数名)赋值给与该函数名同名的变量名,虽然这个地方并未出现函数名加括号,实际上已经调用了outter函数,如果outter函数内部除了定义新函数外还有打印操作,此时运行函数就会打印出内容。

      ③、书写规范

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

    7、多层装饰器

      ①、

    import time
    
    
    user_dic = {'is_login':None}
    
    
    def outter(func):
        def get_time(*args, **kwargs):
            start = time.time()
            res = func(*args, **kwargs)
            end = time.time()
            print('func run time:%s'%(end-start))
            return res
        return get_time
    
    
    def login_auth2(data_source,x,t):
        def login_auth(func):
            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:')
                        password = input('please input your password:')
                        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
    
    
    @login_auth2('file',1,2)
    # 这一步相当于
    # res = login_auth2('file',1,2)  # 这里的res就是login_auth2()的返回值login_auth
    # @res
    @outter
    def index():
        time.sleep(1)
        print('index')
        return 'index'
    
    
    index()
    # 装饰器在装饰的时候,顺序从下往上
    # 装饰器在执行的时候,顺序从上往下
    # 这里就实现了给index函数增加了两个功能:计时和认证
    # 这里的认证函数是三层嵌套的,最外层函数的作用就是给里层函数传参
    

      ②、

    def outter1(func1):
        print('加载了outter1')
        def wrapper1(*args,**kwargs):
            print('执行了wrapper1')
            res1 = func1(*args, **kwargs)
            return res1
        return wrapper1
    def outter2(func2):
        print('加载了outter2')
        def wrapper2(*args,**kwargs):
            print('执行了wrapper2')
            res2 = func2(*args, **kwargs)
            return res2
        return wrapper2
    def outter3(func3):
        print('加载了outter3')
        def wrapper3(*args,**kwargs):
            print('执行了wrapper3')
            res3 = func3(*args, **kwargs)
            return res3
        return wrapper3
    
    
    @outter1
    @outter2
    @outter3
    def index():
        print('from index')
    
    
    index()
    # 输出
    # 加载了outter3
    # 加载了outter2
    # 加载了outter1
    # 执行了wrapper1
    # 执行了wrapper2
    # 执行了wrapper3
    # from index
    

    8、装饰器修复技术

    from functools import wraps
    def outter(func):
        @wraps(func)
        def inner(*args,**kwargs):
            """
            我是inner函数
            :param args:
            :param kwargs:
            :return:
            """
            print('执行被装饰函数之前,你可以执行的操作')
            res = func(*args, **kwargs)
            print('执行被装饰函数之后,你可以执行的操作')
            return res
        return inner
    
    
    @outter
    def index():
        """
        这是index函数
        :return:
        """
        print('from index')
    
    
    print(index)
    # <function index at 0x037646F0>
    print(help(index))
    # Help on function index in module __main__:
    #
    # index()
    #     这是index函数
    #     :return:
    #
    # None
    print(index.__name__)
    # index
    index()
    # 执行被装饰函数之前,你可以执行的操作
    # from index
    # 执行被装饰函数之后,你可以执行的操作
    # 无论是打印index的函数名,还是查看函数的注释,还是查看函数名字的字符串形式,都与原来的index函数一样
    

    9、装饰器模板

      ①、无参装饰器

    from functools import wraps
    
    
    def outter(func):
        @wraps(func)
        def inner(*args, **kwargs):  # * **在形参中使用
            # 执行被装饰函数之前你可以做的操作
            res = func(*args, **kwargs)  # * **在实参中使用
            # 执行被装饰函数之后你可以做到操作
            return res
    
        return inner
    
    
    @outter
    def index(username, *args, **kwargs):
        """index注释"""
        pass
    
    
    print(index)
    

      ②、有参装饰器

    def wrappers(data):
        # data = 'file'
        def outter(func):
            def inner(*args,**kwargs):
                if data == 'file':
                    # 执行被装饰函数之前你可以做的操作
                    res = func(*args,**kwargs)  # * **在实参中使用
                    # 执行被装饰函数之后你可以做到操作
                    return res
            return inner
        return outter
    

      

  • 相关阅读:
    start-stop-daemon 守护进程管理
    Proxmox VE 的安装和简单使用
    查询Linux下文件格式.
    re匹配 [sS][wW]的使用.
    prometheus简单监控Linux,mysql,nginx
    Linux中查看和修改分区的uuid方便挂载使用
    openssl 模块 安装 centso Ubuntu
    python写爬虫遇到需要解码js一些记录
    CSS 文字超出部分显示省略号
    新随笔
  • 原文地址:https://www.cnblogs.com/DcentMan/p/11171851.html
Copyright © 2020-2023  润新知