zoukankan      html  css  js  c++  java
  • 装饰器

    一、补充:nonlocal关键字

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

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

    3、案例:

    def outer():
             num = 10
             print(num) # 10
             def inner():
                   nonlocal num
                   num = 20
                   print(num) # 20
             inner()
             print(num) # 20

    二、装饰器的原则:

    开放封闭原则:不改变调用函数方式与源代码的情况下增加新功能

    1、不能修改被装饰对象(函数)的源代码(封闭)

    2、不能更改被修饰对象(函数)的调用方式,并且能达到增加新功能的效果(开放)

    三、装饰器

    1、原理:

    # 把要被装饰的函数作为外层函数的参数通过闭包操作后返回一个替代版函数
    # 被装饰的函数:fn
    # 外层函数:outer(func) outer(fn) => func = fn
    # 替代版函数: return inner: 原功能+新功能

    2、例:

    def fn():
        print("原有功能")

    # 装饰器
    def outer(tag):
          def inner():
                tag()
                print(新增功能")
           return inner
    fn = outer(fn)
    fn()

    四、@语法糖:@外层函数

    例:

    def 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 check_usr(fn):            # fn, login, inner:不同状态下的login,所以参数是统一的
             def inner(usr, pwd):
             # 在原功能上添加新功能
                       if not (len(usr) >= 3 and usr.isalpha()):
                       print('账号验证失败')
                       return False
                       # 原有功能
                       result = fn(usr, pwd)
                       # 在原功能下添加新功能
                       # ...
                       return result
            return inner


    @check_usr
    def login(usr, pwd):
              if usr == 'abc' and pwd =='123qwe':
                        print('登录成功')
                        return True
              print('登录失败')
              return False

    小结:1、login有参数,所以inner与fn都由相同的参数

                2、longin有返回值,所以inner与fn都由返回值

    六、装饰器的最终写法:

    例:

    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('fn3的原有功能')
           return True
    @wrap
    def fn4(a, *, x):
           print('fn4的原有功能')
           return True

    fn1()
    fn2(10, 20)
    fn3()
    fn4(10, x=20)

    七、带参装饰器

    def outer(input_color):
               def wrap(fn):
                     if input_color == 'red':
                          info = '33[36;41mnew 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: ')
    @outer(color) # @outer(color) ==> @wrap # func => inner
    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('pwd: ')
             if usr == 'abc' and pwd =='123qwe':
                     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
               return inner

    # 查看个人主页功能
    @check_login
    def home():
             print('个人主页')

    # 销售功能
    @check_login
    def sell():
            print('可以销售')

    home()

  • 相关阅读:
    day1-字符串拼接、表达式、break和continue
    ssh免密登录
    1-5 文档的基本 CRUD 与批量操作
    1-4 安装logstash
    1-3 安装cerebro
    1-2 kibana 7.5.1 安装配置
    1-1 elasticsearch7.5 集群搭建 es 7
    生产环境k8s集群搭建
    Gearman任务分布系统部署windows平台_使用Cygwin
    [转载]单元测试之道(使用NUnit)
  • 原文地址:https://www.cnblogs.com/yanminggang/p/10642678.html
Copyright © 2011-2022 走看看