装饰器和递归函数

1.装饰器II

  • 在装饰器 I 中,装饰器应用之一,可以在遵循开放封闭的原则的前提下,加入新功能。但这种添加方法不完善,即:装饰多个函数,必须 “分类讨论”,无法汇总,不具备耦合性。

  • 一个装饰器装饰多个函数(存在参数的装饰器):增强代码的耦合性。

  • 带参数的装饰器基本形式:

    def outer(n):
        def middle(x):
            def inner(*args,**kwargs):
                ……
                调用 n
                a = x(*args,**kwargs)
                return a
              retrun inner
        return middle
    @outer("实参")
    def func():
        pass
    func()
    • Example:

      def wrapper_out(n):
          def wrapper(f):
              def inner(*args, **kwargs):
                  if n == 'qq':
                      username = input('请输入用户名:').strip()
                      password = input('请输入密码:').strip()
                      with open('qq', encoding='utf-8') as f1:
                          for line in f1:
                              user, pwd = line.strip().split('|')
                              if username == user and password == pwd:
                                  print('登陆成功')
                                  ret = f(*args, **kwargs)
                                  return ret
                          return False
                  elif n == 'tiktok':
                      username = input('请输入用户名:').strip()
                      password = input('请输入密码:').strip()
                      with open('tiktok', encoding='utf-8') as f1:
                          for line in f1:
                              user, pwd = line.strip().split('|')
                              if username == user and password == pwd:
                                  print('登陆成功')
                                  ret = f(*args, **kwargs)
                                  return ret
                          return False
                  username = input('请输入用户名:').strip()
                  password = input('请输入密码:').strip()
                  with open(n, encoding='utf-8') as f1:
                      for line in f1:
                          user, pwd = line.strip().split('|')
                          if username == user and password == pwd:
                              print('登陆成功')
                              ret = f(*args, **kwargs)
                              return ret
                      return False
              return inner
          return wrapper
      
      @wrapper_out('qq')
      def qq():
          print('成功访问qq')
      qq()
      
      @wrapper_out('tiktok')
      def tiktok():
          print('成功访问抖音')
      tiktok()
      • 可以通过例子看到,通过将装饰器额外套一层含有形参的函数,可实现对一些重复代码的聚合效果。完成这个额外效果的中间变量,就是形参 n。
      • @最外层函数名("实参") 是在装饰器 I 中, @最外层函数名 的拓展。它代表:
        • 被装饰函数 = 最外层函数名(被装饰函数),此时,当得到调用被装饰函数命令时,@~进行了转译,此时执行的是中层函数,并且此时,实现了传参。
        • 继续按照这个思路走,剩余的步骤便与 “标准模式” 相同。
      • 但是,这个思路还是有其自己的弊端,就是遇到每个被装饰的函数,都要写一层 @~,根据这一点,说明代码的耦合性无法做到最极致。

      • 递归,在一般情况下,相当于无限 while 循环。但操作系统存在内存保护机制,存在最大递归次数。官方默认最大递归次数为:1000 次。
      • 设立保护机制的原因在于,每次调用函数,都会在内存开辟新的空间,而原空间由于函数没有执行完,没有被释放。
      • 原则上,递归的次数应不多余 100 次,为了效率,与时间复杂度。
      • 一般能用递归解决的问题,用 if 与 while 都可以搞定,使用递归在某些时候有奇效。

上一篇:升级vs更新,用词莫忘准确(附PHP版本升级教程)


下一篇:day1