函数的重中之重----装饰器

一、nonlocal关键字

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

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

      # 案例:

            def outer():
              num = 10
              print(num)    # 10

              def inner():
                nonlocal num
                num = 20
                  p77rint(num)   # 20
              inner()
              print(num)     # 20

 

二、开放封闭原则:不改变调用方式与源代码上增加功能

      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 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.login有返回值,所以inner与fn都有返回值

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


login = check_usr(login) = inner

res = login('abc', '123qwe') # inner的返回值

 

六、装饰器最终写法

        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 = '\033[36;41mnew action\33[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()

posted @ 2019-04-04 22:25  西西灬弗斯  阅读(123)  评论(0编辑  收藏  举报