美文网首页
Python-闭包和修饰器

Python-闭包和修饰器

作者: 徐弱西 | 来源:发表于2019-07-14 16:39 被阅读0次

    作用域

    # 作用域:名字起作用的范围
    # 作用:解决同名字可以共存问题 - 不同作用域相同名字的值都能在其作用域范围下进行使用
    '''
    四种作用域: LEGB
    Built-in:内置作用域 - 所有文件所有地方都可以被访问
    Global:全局作用域 - 在当前文件的所有位置
    Enclosing:嵌套作用域 - 自身内部与内部的子函数
    Local:局部作用域 - 只有自身内部
    '''
    # 加载顺序:Built-in > Global > Enclosing > Local
    # 访问(查找)顺序:报错 < Built-in < Global < Enclosing < Local
    # 作用范围:Built-in > Global > Enclosing > Local
    

    闭包

    # 闭包:定义在函数内部的函数,这个内部的函数就是闭包
    
    # 应用场景:
    # 1.可以去使用其他函数的内部变量,且还可以保证调用位置不变(闭包的函数对象作为那个函数的返回值)
    def outer():
        count = 3000
        def fn():
            print(count)  # 能使用outer内部的变量count
        return fn
    # 还是在外界调用
    outer()()  # outer()() => fn() => 调用fn
    
    
    # 2.延迟执行(外层函数可以为内存函数传递参数)
    import requests
    def outer(url):
        def show_html():
            response = requests.get(url)
            print(response.text)
        return show_html
    
    # 制作 爬百度与新浪的 函数对象
    show_baidu = outer('https://www.baidu.com')
    show_sina = outer('https://www.sina.com.cn')
    
    # 延迟到需求来了,需要爬百度,就用百度函数对象,需要爬新浪,就用新浪函数对象
    show_baidu()
    show_sina()
    show_baidu()
    
    code:
    # closure:闭包
    # 闭包:定义在函数内部的函数,这个内部的函数就是闭包
    
    # 应用场景:
    # 1.可以去使用其他函数的内部变量,且还可以保证调用位置不变(闭包的函数对象作为那个函数的返回值)
    def outer():
        count = 3000
        def fn():
            print(count)  # 能使用outer内部的变量count
        return fn
    # 还是在外界调用
    outer()()  # outer()() => fn() => 调用fn
    
    # 2.延迟执行(外层函数可以为内存函数传递参数)
    import requests
    
    # def show_html(url):
    #     response = requests.get(url)
    #     print(response.text)
    #
    # show_html('https://www.baidu.com')
    # show_html('https://www.baidu.com')
    # show_html('https://www.sina.com.cn')
    
    def outer(url):
        def show_html():
            response = requests.get(url)
            print(response.text)
        return show_html
    # 制作 爬百度与新浪的 函数对象
    show_baidu = outer('https://www.baidu.com')
    show_sina = outer('https://www.sina.com.cn')
    # 延迟到需求来了,需要爬百度,就用百度函数对象,需要爬新浪,就用新浪函数对象
    show_baidu()
    show_sina()
    show_baidu()
    
    

    装饰器

    # 装饰器:装饰器就是闭包的一个应用场景
    #       -- 外层函数与内存函数形成的闭包结构的一种综合使用
    
    # 重点:开放封闭原则
    # 开放:拓展功能的点是开放的 - 可以为之前的函数添加新功能
    # 封闭:1.不能改变原函数的源代码  2.还有通过原函数的函数对象来调用函数
    
    def huaping():
        print('插花功能')
    
    temp = huaping
    def my_huaping():
        temp()
        print('观赏功能')
    huaping = my_huaping
    
    huaping()
    
    # ----------------------------------------
    
    def huaping():
        print('插花功能')
    
    def outer(temp):  # temp = huaping
        def my_huaping():
            temp()
            print('观赏功能')
        return my_huaping
    huaping = outer(huaping)  # huaping = my_huaping
    
    huaping()
    
    
    # ----------------------------------------------
    def outer(temp):  # temp = huaping
        def my_huaping():
            temp()
            print('观赏功能')
        return my_huaping
    
    @outer  # huaping = outer(huaping)
    def huaping():
        print('插花功能')
        
    huaping()
    
    
    # ------------------------------------------
    # 被装饰的函数可能有参有返:装饰器模板,可以满足所有参数,且能装饰原函数返回值
    def outer(func):  # temp = huaping
        def inner(*args, **kwargs):
            pass
            res = func(*args, **kwargs)
            pass
            return res
        return inner
    
    @outer
    def any_method():
        pass
    
    
    code:
    # 装饰器:装饰器就是闭包的一个应用场景
    #       -- 外层函数与内存函数形成的闭包结构的一种综合使用
    
    
    # def huaping():
    #     print('插花功能')
    
    # 需求:如何拓展一个原有函数的功能
    #       -- 修改源代码
    #       -- 创建一个包含该功能和其他新功能的新函数
    
    # 开放封闭原则:
    # 开放:拓展功能的点是开放的 - 可以为之前的函数添加新功能
    # 封闭:1.不能改变原函数的源代码  2.还有通过原函数的函数对象来调用函数
    
    # 错误一:修改了源代码
    # def huaping():
    #     print('插花功能')
    #     print('观赏功能')
    # huaping()
    
    # 错误二:改变了调用方式
    # def huaping():
    #     print('插花功能')
    # def my_huaping(fn):
    #     fn()
    #     print('观赏功能')
    # my_huaping(huaping)
    
    # 装饰器:满足开放封闭原则还能拓展新功能,简单
    '''
    def huaping():
        print('插花功能')
    
    temp = huaping
    # temp = '呵呵'
    def my_huaping():
        temp()
        print('观赏功能')
    huaping = my_huaping
    
    huaping()
    '''
    
    # 装饰器演变一:
    '''
    def huaping():
        print('插花功能')
    
    def outer(fn):  # fn = huaping
        # temp = huaping  # 可以提取到实参对形参传递
        def my_huaping():
            fn()
            print('观赏功能')
        return my_huaping
    huaping = outer(huaping)  # 要整合该条逻辑
    
    huaping()
    '''
    
    # 装饰器演变二:
    def outer(fn):  # fn = 原功能的huaping
        def my_huaping():  # my_huaping => 新功能的huaping
            fn()
            print('观赏功能')
        return my_huaping
    
    @outer  # huaping = outer(huaping)  被装饰的函数对象 = 装饰器外层函数对象(被装饰的函数对象)
    def huaping():
        print('插花功能')
    
    huaping()  # 被装饰后的my_huaping
    

    装饰器案例

    # 为登录功能添加账号检验功能:必须是3个及以上英文字母组成
    def check_user(func):
        def inner(user, pwd):
            if not (user.isalpha() and len(user) >= 3):
                return '账号不合法'
            res = func(user, pwd)
            return res
        return inner
    
    # 为登录功能添加密码检验功能:必须是3个及以上英文字母或数字组成
    def check_pwd(func):
        def inner(*args, **kwargs):
            pwd = args[1]
            if not (pwd.isalnum() and len(pwd) >= 3):
                return '密码不合法'
            res = func(*args, **kwargs)
            return res
        return inner
    
    # 对登录结果的修饰装饰器:True=>登录成功 False=>登录失败
    def change_res(func):
        def inner(*args, **kwargs):
            res = func(*args, **kwargs)
            if res == True:
                return '登录成功'
            return '登录失败'
        return inner
    
    
    # 装饰器被执行的过程是从上至下
    @check_user  # login = check_user(func=login) = inner
    @check_pwd
    @change_res
    def login(user, pwd):  # 被装饰的函数对象
        if user == 'owen' and pwd == '123':
            return True
        return False
    
    user = input('user: ')
    pwd = input('pwd: ')
    res = login(user, pwd)
    
    print(res)
    

    code:

    # 为登录功能添加账号检验功能:必须是3个及以上英文字母组成
    def check_user(func):
        def inner(user, pwd):
            if not (user.isalpha() and len(user) >= 3):
                return '账号不合法'
            res = func(user, pwd)
            return res
        return inner
    
    # 为登录功能添加密码检验功能:必须是3个及以上英文字母或数字组成
    def check_pwd(func):
        def inner(*args, **kwargs):
            pwd = args[1]
            if not (pwd.isalnum() and len(pwd) >= 3):
                return '密码不合法'
            res = func(*args, **kwargs)
            return res
        return inner
    
    # 对登录结果的修饰装饰器:True=>登录成功 False=>登录失败
    def change_res(func):
        def inner(*args, **kwargs):
            res = func(*args, **kwargs)
            if res == True:
                return '登录成功'
            return '登录失败'
        return inner
    
    
    @check_user  # login = check_user(func=login) = inner
    @check_pwd
    @change_res
    def login(user, pwd):
        if user == 'owen' and pwd == '123':
            return True
        return False
    
    user = input('user: ')
    pwd = input('pwd: ')
    res = login(user, pwd)
    
    print(res)
    
    
    
    # 装饰器:固定写法
    def outer(func):
        def inner(*args, **kwargs):
            pass
            res = func(*args, **kwargs)
            pass
            return res
        return inner
    
    @outer
    def f1():  # 任意函数
        pass
    f1()
    
    
    
    

    相关文章

      网友评论

          本文标题:Python-闭包和修饰器

          本文链接:https://www.haomeiwen.com/subject/oyxikctx.html