• Python——day12 nonlcoal关键字、装饰器(开放封闭原则、函数被装饰、最终写法)


    一、nonlocal关键字

    1、作用:将L与E(E中的名字需要提前定义)的名字统一

    2、应用场景:如果想在被嵌套的函数中修改外部函数变量(名字)的值

    def outer():
        num=10
        print(num) # 输出结果为10
        def inner():
            nonlocal num
            num=20
            print(num) #输出级结果为20
        inner()
        print(num)   # 输出结果为20
    
    def outer():
        num=0 # 必要写 是用于L与E的名字统一
        def inner():
            # 如果想被嵌套的函数中修改外部函数变量(名字)的值
            nonlocal  num # 将L与E(E中的名字需提前定义好)的名字统一
            num=10
            print(num) # 输出结果为10
        inner()
        print(num ) # 定义了nonlocal就是局部统一,输出结果为10
    outer()
    # print(num)#  属于全局,不能看到其值

    二、开放封闭原则

    1、原则: 不能修改被装饰对象(函数)的源代码——封闭
    不能更改被修饰对象(函数)的调用方式,且能达到增加功能的效果——开放

    1.0版本
    def fn():
        print('fn run ')
    fn()
    
    版本2.0
    def fn2():
        print('fn run 0')
        print('fn run1')
        print('fn run2')
    
    修改了源代码,没有更改调用方式,对外调用方式还是原来的,
    def fn():
        print('fn  run0')
        print('fn run ')
        print('fn run2')
    
     更改了调用方式,没有修改原功能代码块
    def wrap(fn):
        print('fn run0')
        fn()
        print('fn run2')
    wrap(fn)

    三、装饰器


    1、定义:就是闭包(闭包的一个应用场景)
          把要装饰的函数作为外部函数的参数通过闭包操作返回一个替代版函数1

    2、优点:丰富了原有函数的功能
           提高了程序的可拓展性

    把要被装饰的函数作为外层函数的参数通过闭包操作后返回一个替代版函数

    被装饰的函数:fn
    外层函数:outer(func)、outer(fn)==》func=fn
    替代版函数;return inner:原有功能加新功能
    def fn():
        print('原有功能')
    
    # 装饰器
    def outer(tag):
        def inner():
            tag()
            print('新增功能')
            return inner
    fn=outer(fn)
    fn()
    
     案例 花瓶
    def vase():
        print('插花')
     vase()
    
     增加一个绘画后观赏功能
     def  wrap(fn):
         vase()
         print('插花')
         print('绘画:进行观赏')
     wrap(vase)
    
     虽然满足了开放封闭原则,但出现了函数调用死循环
    
     def fn():
         vase()
         print('绘画:进行观赏')
     vase=fn()
     vase()
    
     了解:满足开放fengbiyuanze,且可以达到装饰器的作用:拓展功能
    tag=vase  # 暴露在全局:
     def fn():
         tag()
        print('绘画:进行观赏')
     vase=fn
     vase()
    
    
     满足开放封闭原则(完美方法)
    方式一
    def wrap (tag):
        tag=vase
        def fn():
            tag()
            print('绘画:进行观赏')
        return  fn  # 拓展功能后的vase
    vase =wrap()  # 相当于vase=fn
    vase()
    
    方式二、这个函数嵌套结构就是装饰器
    def wrap (tag):
        def fn():
            tag() # 指原有的vase
            print('绘画:进行观赏')
        return  fn  # 拓展功能后的vase
    vase =wrap(vase)  # 将拓展功能后的函数重新赋值给vase
    vase() # 功能拓展了,且调用方式不变

    四、装饰器的简化语法

    ef outer(f):
        def inner():
            f()
            print("新增功能1")
        return inner
    
    def wrap(f):
        def inner():
            f()
            print("新增功能2")
        return inner
    
    @wrap  # 被装饰的顺序决定了新增功能的执行顺序
    @outer  # <==> fn = outer(fn): inner
    def fn():
        print("原有功能")
    案例:
    
    def outer (fn):
        def inner():
            fn()
            print('绘画:进行观赏')
        return  inner
    
    def wrse (fn):
        def inner():
            fn()
            print('摆放功能')
        return  inner
    
    
    @语法糖|笑笑语法
    
    @wrse
    @outer   #等于这个功能<==>vase =outer(vase)
    def vase():
        print('插花')
    vase()
    
     总结:一个函数可以被任意一个相关装饰器装饰,也可以被任意几个装饰器装饰
     注:装饰的顺序会影响新增功能的执行顺序

    五、有参有返的函数被修饰

    def check_usr(fn):# fn,login,inner:不同状态下的login,所以参数是统一的
        def inner(usr,pwd):
            # 在原功能上添加新功能
             if not(len(usr)>=3and usr.isalpha()):
                print('账号验证失败')
                return False
            #  原有功能
            result=fn(usr,pwd)
        # 在原功能下添加新功能
        #。。。。。()没有添加则用句号省略了
            return result
        return inner
    
    @check_usr
    def login(usr,pwd):
        if usr=='abc'and pwd=='123abc':
            print('登录成功')
            return  True
        print('登录失败')
        return  False

    总结:1、login有参数,所以inner与fn都有相同参数
         2、login有返回值,所以inner与fn都有返回值

    inner(usr, pwd):
    res = fn(usr, pwd) # 原login的返回值
    return res


    login = check_usr(login) = inner

    res = login('abc', '123qwe') # inner的返回值
     案例:
    
    增加一个账号处理功能:3位以上英文字符或汉字
    
    def check_usr(fn):
        def inner(usr,pwd):
            if not (len(usr)>=3 and usr.isalpha()):
                print('账号验证失败')
                return  False
            result=fn(usr,pwd)  #login
            return  result
        return  inner
    
    
    增加一个密码处理功能:6位以上英文和数字
    def check_pwd(fn):
        def inner(usr,pwd):
            if not (len(pwd)>=6 and pwd.isalnum()):
                print('密码验证失败')
                return  False
            return fn(usr,pwd)  #result=fn(usr,pwd)   return result
        return inner
    
    
     登录功能
    @check_usr  # login=check_usr(login)=inner
    def login(usr,pwd):
        if usr=='abc' and pwd=='123abc':
            print('登录成功')
        print('登录失败')
        return False
    
    
    res=login('abc','123abc') # inner  用户名和密码正确输出验证成功
    print(res)

    六、装饰器的最终写法

    # 装饰器的最终写法
    def wrap  (fn):
        def inner(*args,**kwargs):
            print('前增功能')
            result =fn(*args,**kwargs)
            print('后增功能')
            return  result
        return  inner
    
    @wrap
    def fn1():
        print('fn1的原有功能')
    @wrap
    def fn2(a,b): # 有参数无值
        print('fn2的原有功能')
    
    @wrap
    def fn3():# 有返回值无参数
        print('fn2的原有功能')
        return True
    @wrap
    def fn4(a,*,c): #有参数有返回值
        print('fn2的原有功能')
        return True
    
    fn1()
    fn2(10,20)
    fn3()
    fn4(10,c=20)
    
    
    
    
    案例:
     增加一个账号处理功能:3位及以上英文字符或汉字
    def check_usr(fn):
        def inner(usr,pwd):
            if not(len(usr)>=3 and usr.isalpha()):
                print('账号验证失败')
                return  False
            result=fn(usr,pwd) #login
            return result
        return inner
    
    登录功能
    @check_usr
    def login(usr,pwd):
        if usr=='abc'and pwd=='123abc':
            print('登录成功')
            return True
        print('登录失败')
        return False
    
    res=login('abc','123abc')  #inner  账号密码正确打印成功
    print(res)
    带参装饰器
    
    def outer(input_color):
        def wrap(fn):
            if input_color=='red':
                info='33[36;41m  new action33[0m'
            else:
                info='yellow:new action'
            def inner(*args,**kwargs):
                pass
                result=fn(*args,**kwargs)
                print(info)
                return result
            return inner
        return wrap #outer(color)=>>wrap
    
    color=input('color:')
    
    def func():
        print('func run')
    func()

    七、登录认证案例

    is_login=False #登录状态
    def login():
        usr=input('usr:')
        if not(len(usr)>=3 and usr.isalpha()):
            print('账号验证失败')
            return  False
        pwd=input('ped:')
        if usr=='abc'and pwd=='123abc':
            print('登录成功')
            is_login=True
        else:
            print('登录失败')
            is_login=False
    
    完成一个登录状态校验的装饰器
    
    def check_login(fn):
        def inner(*args,**kwargs):
            # 查看个人主页或销售功能前:如果没有登录需要先登录,繁殖可以进入其功能
            if is_login!=True:
                print('你未登录')
                login()
                # 查看个人主页或销售
            result=fn(*args,**kwargs)
            return  result
    
    查看个人主页功能
    @check_login
    def home():
        print('个人主页')
    
    
    销售功能
    @check_login
    def sell():
        print('可以销售')
    home()
  • 相关阅读:
    PsySH——PHP交互式控制台
    PHP通过ssh或socks5读取远程服务器的mysql数据库
    构建:vue项目配置后端接口服务信息
    module.exports用法
    PhpStorm连接服务器,开始自动上传功能
    JavaScript Array.some()方法用法
    vue-router query和params传参(接收参数),$router、$route的区别
    ES6箭头函数(Arrow Functions)
    工作中常用到的ES6语法
    VueJs2.0建议学习路线
  • 原文地址:https://www.cnblogs.com/zhouqinmei/p/10643693.html
Copyright © 2020-2023  润新知