Python基础(十四)

2020-12-13 16:17

阅读:578

  • 回顾一下之前的游戏模拟,通过装饰器给我的游戏过程扩展了开挂的功能,装饰之后每次想玩游戏的时候调用函数都会给你先把挂打开,此时你的游戏函数已经被装饰了,但是现在有一个问题,我今天想自己玩一把,不想开挂了,怎么办?我们可以给装饰器传一个参数,来控制我的装饰器的开启和关闭就可以了

    def wrapper_outer(argv):  # 给装饰器加一个参数,控制装饰器开启关闭
        def wrapper(fn):
            def inner(hero): 
                if argv:  # 如果是True执行添加装饰
                    print("开启外挂!")
                    ret = fn(hero)
                    print("关闭外挂!")
                    return ret
                else:  # 如果是False,执行原函数
                    ret = fn(hero)
                    return ret
            return inner
        return wrapper
    
    @wrapper_outer(True)
    def play_lol(hero):  # 基础函数参数
      print("登陆游戏")
      print("开始排位...")
      print(f"选择英雄:{hero}")
      print("游戏中...")
      print("胜利!!!")
      print("结束游戏")
      return "坑比队友:xxx"  # 基础函数返回值
    
    print(play_lol("盖伦"))
    
    运行结果:
    开启外挂!
    登陆游戏
    开始排位...
    选择英雄:盖伦
    游戏中...
    胜利!!!
    结束游戏
    关闭外挂!
    坑比队友:xxx
    • 刨析一下:

      • 先来看装饰器和语法糖
        • @wrapper_outer(True)先执行函数调用,函数调用返回的是我内层装饰器的函数名,相当于@wrapper
        • 装饰器最外层的参数控制内层包装函数inner里面的函数部分是否执行,如果argv为真,相当于执行了包装,如果argv为假,执行原函数
      • 通过给装饰器传参起到了控制装饰器是否生效的功能
      def wrapper_outer(argv):
          def wrapper(fn):
              def inner(hero):  
                  if argv:  # 为真执行这里
                      print("开启外挂!")
                      ret = fn(hero)
                      print("关闭外挂!")
                      return ret
                  else:  # 为假执行这里
                      ret = fn(hero)
                      return ret
              return inner
          return wrapper
      
      @wrapper_outer(True)  # 先执行函数调用
      • 注意:一旦给函数装饰过,装饰器的参数是不能变化的,因为闭包的原因参数已经被闭进去了,只能调用内层函数,无法再修改最外层的装饰器参数
      flag = True
      def wrapper_outer(argv):
          def wrapper(fn):
              def inner(*args, **kwargs):  
                  if argv:
                      """扩展功能"""
                      ret = fn(*args, **kwargs)
                      """扩展功能"""
                      return ret
                  else:
                      ret = fn(*args, **kwargs)
                      return ret
              return inner
          return wrapper
      
      @wrapper_outer(flag)
      def func():
          pass
      
      flag = False
      func()  # 此时flag依然是True,装饰过就不能修改参数的值

  • 评论


    亲,登录后才可以留言!