Pythonの基礎(XIV)

今日メインコンテンツ

  • 装飾的な拡張
    • パラメータデコレータがあります。
    • 装飾的な機能デコレータの複数
  • 再帰

装飾的な拡張

パラメータデコレータと(A)

  • 標準モードデコレータ初めて目に

    def wrapper(fn):
      def inner(*args, **kwargs):
          """扩展内容"""
          ret = fn(*args, **kwargs)
          """扩展内容"""
      return inner
    
    @wrapper
    def func():
      pass
    
    func()
  • ゲーム中に私にデコレータによって前にリコールシミュレーションゲームは、オープンぶら下がって機能を拡張し、その後、それぞれがあなたが最初の関数を呼び出すときにゲームをプレイしたい飾ることは開いてハングアップすることになり、その後、あなたのゲーム機能が装飾されていますが、今ご質問があり、私は今日1を自分でプレイしたい、私は何をするか、ハングアップしたくありませんか?私たちは、デコレータにパラメータを渡すことができ、その上にオンとオフ私のデコレータを制御します

    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
        • 関数は、インナーラッパー関数内で実行trueの場合argvを、パッケージの等価を行う、falseの場合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,装饰过就不能修改参数的值
  • 標準モードのデコレータを参照

    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(True)
    def func():
        pass
    
    func()

(B)装飾関数デコレータの複数

  • 原則の実装:内部から梱包アウト

    def wrapper1(fn):
      def inner(*args, **kwargs):
          print("扩展功能1")
          ret = fn(*args, **kwargs)
          print("扩展功能4")
          return ret
      return inner
    
    def wrapper2(fn):
      def inner(*args, **kwargs):
          print("扩展功能2")
          ret = fn(*args, **kwargs)
          print("扩展功能3")
          return ret
      return inner
    
    @wrapper1
    @wrapper2
    def func():
      print("目标函数")
    
    func()
    
    运行结果:
    扩展功能1
    扩展功能2
    目标函数
    扩展功能3
    扩展功能4
    • 飛行機についての分析:

      • 内側から、まず、第1層のデコレータで、外を見て@wrapper2装飾的な目的関数func()全体としての装飾仕上げ、上位ビーイングデコレータとみなされ、@wrapper1装飾
      • 戻り値:目的関数の完全な実装は、最寄りの最初の抗デコレータ目的関数の値を返します。@wrapper2そして後に、内側の包装関数内で@wrapper2内部のパッケージング機能のデコレータ内層への戻り値は@wrapper1、内部のインテリア戻り値は、私は関数の戻り値を呼び出してしまうということです
      • 最終目的関数の呼び出しは、実際には、最も外側のデコレータのラッパー関数の実際の実装でinner最も外側のデコレータラッパー関数ながら、innerラッパー関数内部デコレータ付きパッケージinner、デコレータとの内側のラッパー関数inner本物のパッケージングヘッドテーブル機能func
      # 伪代码:
      
      def 装饰器1(传入目标函数):
          def 内层包装函数1,也是真正执行的函数(目标函数的参数):
              """前扩展功能"""
              目标函数(目标函数的参数)
              """后扩展功能"""
          return 包装函数的函数名
      
      def 装饰器2(传入目标函数):
          def 内层包装函数2,也是真正执行的函数(目标函数的参数):
              """前扩展功能"""
              目标函数(目标函数的参数)
              """后扩展功能"""
          return 包装函数的函数名
      
      @装饰器1
      @装饰器2
      def 目标函数(形参):
          函数体
      
      目标函数(实参)
      
      # 真正执行过程:
      先执行:装饰器1的内层包装函数1,而传入的目标函数是:装饰器2的内层包装函数2
      再执行:装饰器2的内层包装函数2,而传入的目标函数是:目标函数

第二に、再帰

(A)再帰的である何

  • 最初は限り関数は再帰関数2つの要件を満たすためにあるように、再帰関数であります:
    • 自分自身を呼び出すために続けて
    • 明確な終了条件があります。

(B)再帰の深さ

  • あなただけの明確な終了条件なしに、自分自身を呼び出すために続けば、それは死んで再帰的(無限ループ)です。

  • Pythonの公式規則は、再帰の最大の深さが1000である無制限の通話自体を避けるために、再帰998の実際の深さを(のみ1000年に自分自身を呼び出すことができます)

    def func():
        print(1)
        func()
    
    func()
    
    运行结果:
    [Previous line repeated 994 more times]
    1
    1
    1
    ...(共打印998个1)
  • SYSモジュールを導入することにより、再帰の最大の深さを変更します

    import sys
    sys.setrecursionlimit(100)  # 修改递归深度
    
    def func():
        print(1)
        func()
    
    func()
    
    运行结果:
    [Previous line repeated 94 more times]
    1
    1
    1
    ...(实际打印98个1)

(C)は、再帰的に適用しました

  1. n個の階乗

    def factorial(n):
        if n == 1:
            return 1
        return factorial(n - 1) * n
    
    print(factorial(5))
    
    运行结果:
    120
  2. フィボナッチ数列の計算

    def fib(n):
     if n <= 2:
         return 1
     return fib(n-1) + fib(n-2)
    
    print(list(map(fib,range(1, 6))))
    
    运行结果:
    [1, 1, 2, 3, 5]
  3. ネストされたリストに各要素を印刷

    l1 = [1, 2, [3, 4, [5, [6, 7, [8, 9], 10], 11, 12], 13], 14, 15]
    
    def func(lst):
        for el in lst:
            if type(el) == list:
                func(el)
            else:
                print(el, end=" ")
    
    func(l1)
    
    运行结果:
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 
  4. 重いのリストに移動し、あなたが集計を使用することはできません

    l1 = [1, 1, 2, 3, 4, 5, 6, 3, 3, 5, 6, 3, 4, 5]
    
    def del_repetition(lst):
        for el in lst:
            if lst.count(el) > 1:
                lst.remove(el)
                del_repetition(lst)
    
    del_repetition(l1)
    print(l1)
    
    运行结果:
    [1, 2, 6, 3, 4, 5]
  5. すべてのファイルフォルダのスキャン

    import os
    
    def read(filepath, n):
        files = os.listdir(filepath)  # 获取到当前文件夹中的所有文件
        for fi in files:  # 遍历文件夹中的文件, 这里获取的只是本层文件名
            fi_d = os.path.join(filepath, fi)  # 加入文件夹 获取到文件夹文件
            if os.path.isdir(fi_d):  # 如果该路径下的文件是文件夹
                print("\t" * n, fi)
                read(fi_d, n + 1)  # 继续进行相同的操作
            else:
                print("\t" * n, fi)  # 递归出口. 最终在这里隐含着return
    
    # 递归遍历目录下所有文件
    read('../day16/', 0)
  6. バイナリ検索

    # 普通递归版本⼆二分法
    lst = [22, 33, 44, 55, 66, 77, 88, 99, 101, 238, 345, 456, 567, 678, 789]
    n = 567
    left = 0
    right = len(lst) - 1
    
    def binary_search(n, left, right):
        if left <= right:
            middle = (left + right) // 2
            if n < lst[middle]:
                right = middle - 1
            elif n > lst[middle]:
                left = middle + 1
            else:
                return middle
            return binary_search(n, left, right)  
            # 这个return必须要加. 否则接收到的永远是None.
        else:
            return -1
    
    print(binary_search(567, 0, len(lst) - 1))
  7. 3レベルのメニューに戻ります

    menu = {
        '北京': {
            '海淀': {
                '五道口': {
                    'soho': {},
                    '网易': {},
                    'google': {}
                },
                '中关村': {
                    '爱奇艺': {},
                    '汽车之家': {},
                    'youku': {},
                },
                '上地': {
                    '百度': {},
                },
            },
            '昌平': {
                '沙河': {
                    '北邮': {},
                    '北航': {},
                },
                '天通苑': {},
                '回龙观': {},
            },
            '朝阳': {},
            '东城': {},
        },
        '上海': {
            '闵行': {
                "人民广场": {
                    '炸鸡店': {}
                }
            },
            '闸北': {
                '火车战': {
                    '携程': {}
                }
            },
            '浦东': {},
        },
        '天津': {
            "和平": {
                "小白楼": {},
                "五大道小洋楼": {},
                "滨江道": {},
            },
            "南开": {
                "天大": {},
                "南开": {},
                "理工": {},
            },
            "河北": {
                "天津之眼": {},
                "海河": {},
                "意式风情区": {},
                "世纪钟": {},
                "大悲院": {},
            },
        },
    }
    
    def menu_func(menu):
        while True:
            for k in menu:
                print(k)
            key = input('input>>').strip()
            if key == 'b' or key == 'q':
                return key
            elif menu.get(key):
                ret = menu_func(menu[key])
                if ret == 'q': 
                    return 'q'
    
    menu_func(menu)

おすすめ

転載: www.cnblogs.com/tianlangdada/p/11619068.html