"functools" --- 高階関数と呼び出し可能オブジェクトの操作
********************************************************

**ソースコード:** Lib/functools.py

======================================================================

"functools" モジュールは、ほかの関数を操作したり返したりする高階関数の
ためのモジュールです。 一般に、このモジュールではあらゆる呼び出し可能
オブジェクトを関数として扱えます。

"functools" モジュールは次の関数を定義しています。

@functools.cache(user_function)

   簡単で軽量な無制限の関数キャッシュです。 "メモ化 (memoize)" とも呼
   ばれることがあります。

   "lru_cache(maxsize=None)" と同じものを返します。 関数の引数を辞書で
   検索する処理を薄いラッパーで包んだものです。 古い値を削除する必要が
   ないため、サイズ制限付きの "@lru_cache" より小さく高速です。

   例えば:

      @cache
      def factorial(n):
          return n * factorial(n-1) if n else 1

      >>> factorial(10)   # キャッシュ済みの結果がないため、11 回再帰呼び出しする
      3628800
      >>> factorial(5)    # 新たな呼び出しをせず、キャッシュ済みの結果を返す
      120
      >>> factorial(12)   # 2 回新たに再帰呼び出しする。factorial(10) はキャッシュ済み
      479001600

   キャッシュはスレッドセーフなので、ラップされた関数を複数のスレッド
   で使用できます。 これは、同時に更新が行われても、内部のデータ構造の
   整合性が保たれるという意味です。

   最初の呼び出しが完了して結果がキャッシュされるまでに別のスレッドか
   ら呼び出された場合、ラップされた関数が複数回呼び出される可能性があ
   ります。

   関数の呼び出し中はロックを保持しないため、呼び出しが 1 回だけになる
   保証はありません。 最初の呼び出しがまだ実行中でも、同じ引数で別の呼
   び出しが行われる可能性があります。

   Added in version 3.9.

@functools.cached_property(func)

   クラスのメソッドをプロパティに変換します。 その値は一度だけ計算され
   、インスタンスが存続する間は通常の属性としてキャッシュされます。
   "@property" にキャッシュ機能を追加したようなものです。 それ以外の点
   では実質的にイミュータブルなインスタンスで、計算に時間のかかるプロ
   パティに役立ちます。

   以下はプログラム例です:

      class DataSet:

          def __init__(self, sequence_of_numbers):
              self._data = tuple(sequence_of_numbers)

          @cached_property
          def stdev(self):
              return statistics.stdev(self._data)

   "@cached_property" の仕組みは "@property" と少し異なります。 通常の
   プロパティでは、セッターが定義されていない限り属性への書き込みがで
   きません。 これに対して *cached_property* は書き込みを許可します。

   *cached_property* デコレータが実行されるのは、属性が検索され、かつ
   同名の属性がまだ存在しない場合だけです。 実行されると、
   *cached_property* は同名の属性に値を書き込みます。 その後の属性の読
   み書きは *cached_property* メソッドより優先されるため、通常の属性と
   同じように動作します。

   キャッシュされた値は属性を削除することで取り除くことができます。こ
   れにより *cached_property* メソッドを再度実行することが可能になりま
   す。

   *cached_property* は、複数スレッドで使用する際に起こり得る競合状態
   を防ぎません。 同じインスタンスに対してゲッター関数が複数回実行され
   、最後の実行がキャッシュの値を設定する場合があります。 キャッシュさ
   れるプロパティが冪等であるなど、同じインスタンスで複数回実行しても
   害がなければ問題ありません。 同期が必要な場合は、デコレートしたゲッ
   ター関数内か、キャッシュされるプロパティにアクセスする箇所の前後で
   、必要なロックを実装してください。

   このデコレータは **PEP 412** のキー共有辞書の動作を妨げる点に注意し
   てください。 そのため、インスタンスの辞書が通常より多くのメモリを使
   うことがあります。

   また、このデコレータは各インスタンスの "__dict__" 属性が可変のマッ
   ピングであることを要求します。すなわち、このデコレータはいくつかの
   型、たとえばメタクラス (型インスタンスの "__dict__" 属性はクラスの
   名前空間に対する読み込み専用のプロキシであるため) や、 "__slots__"
   を指定していてその中に "__dict__" を含まない型 (それ自体が
   "__dict__" 属性を提供しないため) に対しては動作しないことを意味しま
   す。

   ミュータブルなマッピングを利用できない場合や、キーを共有してメモリ
   を節約したい場合は、"@lru_cache" の上に "@property" を重ねることで
   も "@cached_property" に似た効果を得られます。 "@cached_property"
   との違いについては メソッド呼び出しをキャッシュするには どうしたら
   いいですか？ を参照してください。

   Added in version 3.8.

   バージョン 3.12 で変更: Python 3.12 より前の "@cached_property" に
   はドキュメントに記載されていないロックがあり、複数スレッドで使用し
   てもゲッター関数がインスタンスごとに 1 回だけ実行されるよう保証して
   いました。 しかし、このロックはインスタンス単位ではなくプロパティ単
   位だったため、ロックの競合が許容できないほど多くなる場合がありまし
   た。 Python 3.12 以降では、このロックは削除されています。

functools.cmp_to_key(func)

   古いスタイルの比較関数を *key function* に変換します。key 関数を受
   け取るツール ("sorted()", "min()", "max()", "heapq.nlargest()",
   "heapq.nsmallest()", "itertools.groupby()" など) と共に使用します。
   この関数は、主に比較関数を使っていた Python 2 からプログラムの移行
   のための変換ツールとして使われます。

   比較関数は2つの引数を受け取り、それらを比較し、 "より小さい" 場合は
   負の数を、同値の場合には 0 を、 "より大きい" 場合には正の数を返す、
   あらゆる呼び出し可能オブジェクトです。key 関数は呼び出し可能オブジ
   ェクトで、1つの引数を受け取り、ソートキーとして使われる値を返します
   。

   以下はプログラム例です:

      sorted(iterable, key=cmp_to_key(locale.strcoll))  # ロケールに応じた順序でソート

   ソートの例と簡単なチュートリアルは ソートのテクニック を参照して下
   さい。

   Added in version 3.2.

@functools.lru_cache(user_function)
@functools.lru_cache(maxsize=128, typed=False)

   関数をメモ化用の呼び出し可能オブジェクトでラップし、最近の呼び出し
   最大 *maxsize* 回まで保存するするデコレータです。高価な関数や I/O
   に束縛されている関数を定期的に同じ引数で呼び出すときに、時間を節約
   できます。

   キャッシュはスレッドセーフなので、ラップされた関数を複数のスレッド
   で使用できます。 これは、同時に更新が行われても、内部のデータ構造の
   整合性が保たれるという意味です。

   最初の呼び出しが完了して結果がキャッシュされるまでに別のスレッドか
   ら呼び出された場合、ラップされた関数が複数回呼び出される可能性があ
   ります。

   結果のキャッシュには辞書が使われるので、関数の位置引数およびキーワ
   ード引数は *ハッシュ可能* でなくてはなりません。

   引数のパターンが異なると、別の呼び出しとして扱われ、個別のキャッシ
   ュエントリーになることがあります。 例えば、"f(a=1, b=2)" と "f(b=2,
   a=1)" はキーワード引数の順序が異なるため、2 つの別々のキャッシュエ
   ントリーになる可能性があります。

   *user_function* が指定された場合、それは呼び出し可能でなければなり
   ません。これにより *lru_cache* デコレータがユーザー関数に直接適用で
   きるようになります。このとき *maxsize* の値はデフォルトの 128 とな
   ります:

      @lru_cache
      def count_vowels(word):
          return sum(word.count(vowel) for vowel in 'AEIOUaeiou')

   *maxsize* が "None" に設定された場合は、LRU 機能は無効化され、キャ
   ッシュは際限無く大きくなります。

   *typed* を真にすると、型の異なる関数の引数は別々にキャッシュされま
   す。 *typed* が偽の場合、通常は同等の呼び出しとして扱われ、結果は 1
   つだけキャッシュされます。 (*str* や *int* など、*typed* が偽でも別
   々にキャッシュされる型もあります。)

   型の区別は関数に直接渡す引数にだけ適用され、その内容には適用されな
   い点に注意してください。 スカラーの引数 "Decimal(42)" と
   "Fraction(42)" は、結果の異なる別々の呼び出しとして扱われます。 一
   方、タプルの引数 "('answer', Decimal(42))" と "('answer',
   Fraction(42))" は同等として扱われます。

   ラップされた関数には、*maxsize* と *typed* の値を示す新しい "dict"
   を返す "cache_parameters()" 関数が追加されます。 これは情報を得るた
   めだけのもので、値を変更しても効果はありません。

   キャッシュの効果の測定や *maxsize* 引数の調整に役立つように、ラップ
   された関数には "cache_info()" 関数が追加されます。 この関数は
   *hits*、*misses*、*maxsize*、*currsize* を示す *名前付きタプル* を
   返します。

   このデコレータはキャッシュを消去または無効化するための
   "cache_clear()" 関数も提供します。

   ラップされた元の関数には "__wrapped__" 属性でアクセスできます。 こ
   れは内観やキャッシュの回避、別のキャッシュによる関数のラップし直し
   に便利です。

   引数と戻り値への参照は、古くなってキャッシュから削除されるか、キャ
   ッシュが消去されるまで保持されます。

   メソッドをキャッシュする場合、インスタンスの引数 "self" もキャッシ
   ュに含まれます。 メソッド呼び出しをキャッシュするには どうしたらい
   いですか？ を参照してください。

   LRU (least recently used) キャッシュ は、最近の呼び出しから今後の呼
   び出しをよく予測できる場合に最も効果を発揮します (例えば、ニュース
   サーバーで人気の記事は日ごとに変わる傾向があります)。 キャッシュの
   サイズ制限により、ウェブサーバーなど長時間実行するプロセスでもキャ
   ッシュが際限なく増えることを防ぎます。

   一般に LRU キャッシュは、以前計算した値を再利用したい場合にのみ使っ
   てください。 したがって、副作用のある関数、呼び出すたびに別のミュー
   タブルなオブジェクトを作る必要のある関数 (ジェネレータや非同期関数
   など)、time() や random() のような純粋でない関数をキャッシュしても
   意味がありません。

   静的 web コンテンツ の LRU キャッシュの例:

      @lru_cache(maxsize=32)
      def get_pep(num):
          'Python Enhancement Proposal のテキストを取得する'
          resource = f'https://peps.python.org/pep-{num:04d}'
          try:
              with urllib.request.urlopen(resource) as s:
                  return s.read()
          except urllib.error.HTTPError:
              return 'Not Found'

      >>> for n in 8, 290, 308, 320, 8, 218, 320, 279, 289, 320, 9991:
      ...     pep = get_pep(n)
      ...     print(n, len(pep))

      >>> get_pep.cache_info()
      CacheInfo(hits=3, misses=8, maxsize=32, currsize=8)

   キャッシュを使って 動的計画法 の技法を実装し、フィボナッチ数 を効率
   よく計算する例:

      @lru_cache(maxsize=None)
      def fib(n):
          if n < 2:
              return n
          return fib(n-1) + fib(n-2)

      >>> [fib(n) for n in range(16)]
      [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]

      >>> fib.cache_info()
      CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)

   Added in version 3.2.

   バージョン 3.3 で変更: *typed* オプションが追加されました。

   バージョン 3.8 で変更: *user_function* オプションが追加されました。

   バージョン 3.9 で変更: "cache_parameters()" 関数が追加されました。

@functools.total_ordering

   ひとつ以上の拡張順序比較メソッド (rich comparison ordering methods)
   を定義したクラスを受け取り、残りを実装するクラスデコレータです。こ
   のデコレータは全ての拡張順序比較演算をサポートするための労力を軽減
   します:

   クラスには "__lt__()"、"__le__()"、"__gt__()"、"__ge__()" のいずれ
   かを定義する必要があります。 加えて "__eq__()" メソッドも用意してく
   ださい。

   例えば:

      @total_ordering
      class Student:
          def _is_valid_operand(self, other):
              return (hasattr(other, "lastname") and
                      hasattr(other, "firstname"))
          def __eq__(self, other):
              if not self._is_valid_operand(other):
                  return NotImplemented
              return ((self.lastname.lower(), self.firstname.lower()) ==
                      (other.lastname.lower(), other.firstname.lower()))
          def __lt__(self, other):
              if not self._is_valid_operand(other):
                  return NotImplemented
              return ((self.lastname.lower(), self.firstname.lower()) <
                      (other.lastname.lower(), other.firstname.lower()))

   注釈:

     このデコレータにより、このデコレータにより、行儀の良い（well
     behaved）全順序型を簡単に作ることができますが、その代償として実行
     速度は遅く、比較メソッドの演繹によってのスタックトレースは複雑に
     なります。性能ベンチマークにより、これがアプリケーションのボトル
     ネックになっていることがわかった場合は、代わりに 6 つの拡張比較メ
     ソッドをすべて実装すれば、簡単にスピードアップを図れるでしょう。

   注釈:

     このデコレータは、クラス *またはそのスーパークラス* で宣言されて
     いるメソッドをオーバーライドしません。 つまり、スーパークラスが比
     較演算子を定義している場合は、元のメソッドが抽象メソッドであって
     も *total_ordering* はそれを再実装しません。

   Added in version 3.2.

   バージョン 3.4 で変更: 認識できない型に対して、元の比較関数が
   "NotImplemented" を返すことをサポートしました。

functools.Placeholder

   "partial()" や "partialmethod()" の呼び出し時に、位置引数の場所を確
   保するための番兵として使うシングルトンオブジェクトです。

   Added in version 3.14.

functools.partial(func, /, *args, **keywords)

   新しい partial オブジェクト を返します。このオブジェクトは呼び出さ
   れると位置引数 *args* とキーワード引数 *keywords* 付きで呼び出され
   た *func* のように振る舞います。呼び出しに際してさらなる引数が渡さ
   れた場合、それらは *args* に付け加えられます。追加のキーワード引数
   が渡された場合には、それらで *keywords* を拡張または上書きします。
   おおよそ次のコードと等価です:

      def partial(func, /, *args, **keywords):
          def newfunc(*more_args, **more_keywords):
              return func(*args, *more_args, **(keywords | more_keywords))
          newfunc.func = func
          newfunc.args = args
          newfunc.keywords = keywords
          return newfunc

   "partial()" 関数は関数の部分適用に使います。 関数の位置引数やキーワ
   ード引数の一部を「固定」し、より単純なシグネチャの新しいオブジェク
   トを作ります。 例えば "partial()" を使うと、*base* 引数のデフォルト
   が "2" である点を除いて "int()" 関数と同じように動作する、呼び出し
   可能オブジェクトを作れます。

      >>> basetwo = partial(int, base=2)
      >>> basetwo.__doc__ = '2 進数の文字列を int に変換する。'
      >>> basetwo('10010')
      18

   *args* に "Placeholder" の番兵が含まれている場合、"partial()" の呼
   び出し時にはその位置が先に埋められます。 これにより、"partial()" の
   呼び出しで任意の位置引数をあらかじめ埋められます。 "Placeholder" が
   なければ、先頭から指定した個数の位置引数しか埋められません。

   "Placeholder" の番兵が含まれる場合、呼び出し時にすべてを埋める必要
   があります。

      >>> say_to_world = partial(print, Placeholder, Placeholder, "world!")
      >>> say_to_world('Hello', 'dear')
      Hello dear world!

   "say_to_world('Hello')" を呼び出すと "TypeError" を送出します。 埋
   めるべきプレースホルダーが 2 つあるのに、位置引数が 1 つしか渡され
   ていないためです。

   既存の partial オブジェクト に "partial()" を適用すると、入力オブジ
   ェクトの "Placeholder" の番兵が新しい位置引数で埋められます。 元の
   "Placeholder" の位置に新しい "Placeholder" の番兵を入れると、プレー
   スホルダーを維持できます。

      >>> from functools import partial, Placeholder as _
      >>> remove = partial(str.replace, _, _, '')
      >>> message = 'Hello, dear dear world!'
      >>> remove(message, ' dear')
      'Hello, world!'
      >>> remove_dear = partial(remove, _, ' dear')
      >>> remove_dear(message)
      'Hello, world!'
      >>> remove_first_dear = partial(remove_dear, _, 1)
      >>> remove_first_dear(message)
      'Hello, dear world!'

   "Placeholder" をキーワード引数として "partial()" に渡すことはできま
   せん。

   バージョン 3.14 で変更: 位置引数での "Placeholder" のサポートが追加
   されました。

class functools.partialmethod(func, /, *args, **keywords)

   "partial" と似た動作をする新しい "partialmethod" 記述子 (デスクリプ
   タ) を返します。直接呼び出しではなく、メソッド定義としての使用が目
   的であることのみが、partial とは異なります。

   *func* は、*descriptor* または呼び出し可能オブジェクトである必要が
   あります (通常の関数など、両方の性質を持つオブジェクトは記述子とし
   て扱われます。)

   *func* がデスクリプタ (通常の Python 関数、"classmethod()"、
   "staticmethod()"、"abstractmethod()"、別の "partialmethod" インスタ
   ンスなど) の場合、"__get__" の呼び出しは元のデスクリプタに委譲され
   、適切な partial オブジェクト が返されます。

   *func* が記述子ではない呼び出し可能オブジェクトの場合、適切な束縛メ
   ソッドを動的に作成します。 これは通常の Python 関数をメソッドとして
   使う場合と同じように動作します。 *self* 引数は、"partialmethod" コ
   ンストラクタに渡した *args* や *keywords* よりも前に、最初の位置引
   数として挿入されます。

   以下はプログラム例です:

      >>> class Cell:
      ...     def __init__(self):
      ...         self._alive = False
      ...     @property
      ...     def alive(self):
      ...         return self._alive
      ...     def set_state(self, state):
      ...         self._alive = bool(state)
      ...     set_alive = partialmethod(set_state, True)
      ...     set_dead = partialmethod(set_state, False)
      ...
      >>> c = Cell()
      >>> c.alive
      False
      >>> c.set_alive()
      >>> c.alive
      True

   Added in version 3.4.

functools.reduce(function, iterable, /[, initial])

   2 つの引数を取る *function* を、*iterable* の要素に左から右へ累積的
   に適用し、単一の値にまとめます。 例えば "reduce(lambda x, y: x+y,
   [1, 2, 3, 4, 5])" は "((((1+2)+3)+4)+5)" を計算します。 左の引数
   *x* は累積した値、右の引数 *y* は *iterable* から得た、更新に使う値
   です。 省略可能な *initial* を指定すると、計算時に "iterable" の要
   素より前に置かれ、"iterable" が空の場合のデフォルト値にもなります。
   *initial* を指定せず、*iterable* に要素が 1 つしかない場合は、その
   要素を返します。

   およそ次と等価です:

      initial_missing = sentinel('initial_missing')

      def reduce(function, iterable, /, initial=initial_missing):
          it = iter(iterable)
          if initial is initial_missing:
              value = next(it)
          else:
              value = initial
          for element in it:
              value = function(value, element)
          return value

   全ての中間値を返すイテレータについては "itertools.accumulate()" を
   参照してください。

   バージョン 3.14 で変更: *initial* をキーワード引数として指定できる
   ようになりました。

@functools.singledispatch

   関数を *シングルディスパッチ* *ジェネリック関数* に変換します。

   ジェネリック関数を定義するには、"@singledispatch" デコレータを付け
   ます。 "@singledispatch" で関数を定義する場合、ディスパッチは最初の
   引数の型に基づく点に注意してください。

      >>> from functools import singledispatch
      >>> @singledispatch
      ... def fun(arg, verbose=False):
      ...     if verbose:
      ...         print("Let me just say,", end=" ")
      ...     print(arg)

   関数にオーバーロードした実装を追加するには、ジェネリック関数の
   "register()" 属性を使います。 この属性はデコレータとして使用できま
   す。 型アノテーションのある関数の場合、デコレータは最初の引数の型を
   自動的に推論します。

      >>> @fun.register
      ... def _(arg: int, verbose=False):
      ...     if verbose:
      ...         print("Strength in numbers, eh?", end=" ")
      ...     print(arg)
      ...
      >>> @fun.register
      ... def _(arg: list, verbose=False):
      ...     if verbose:
      ...         print("Enumerate this:")
      ...     for i, elem in enumerate(arg):
      ...         print(i, elem)

   "typing.Union" も使えます。

      >>> @fun.register
      ... def _(arg: int | float, verbose=False):
      ...     if verbose:
      ...         print("Strength in numbers, eh?", end=" ")
      ...     print(arg)
      ...
      >>> from typing import Union
      >>> @fun.register
      ... def _(arg: Union[list, set], verbose=False):
      ...     if verbose:
      ...         print("Enumerate this:")
      ...     for i, elem in enumerate(arg):
      ...         print(i, elem)
      ...

   型アノテーションを使っていないコードについては、デコレータに適切な
   型引数を明示的に渡せます:

      >>> @fun.register(complex)
      ... def _(arg, verbose=False):
      ...     if verbose:
      ...         print("Better than complicated.", end=" ")
      ...     print(arg.real, arg.imag)
      ...

   コレクションの型 (例: "list") に基づいてディスパッチし、その要素に
   は型ヒント (例: "list[int]") を付けたい場合は、ディスパッチに使う型
   をデコレータに明示的に渡し、型ヒントは関数定義に記述してください。

      >>> @fun.register(list)
      ... def _(arg: list[int], verbose=False):
      ...     if verbose:
      ...         print("Enumerate this:")
      ...     for i, elem in enumerate(arg):
      ...         print(i, elem)

   注釈:

     実行時には、リストに含まれる要素の型に関係なく、リストのインスタ
     ンスに対して同じ実装を選びます。 つまり、"[1,2,3]" と "["foo",
     "bar", "baz"]" は同じようにディスパッチされます。 この例のアノテ
     ーションは静的型チェッカーのためだけのもので、実行時には影響しま
     せん。

   *ラムダ式* や既存の関数を登録できるように、"register()" 属性は関数
   として呼び出すこともできます。

      >>> def nothing(arg, verbose=False):
      ...     print("Nothing.")
      ...
      >>> fun.register(type(None), nothing)

   "register()" 属性は、デコレートする前の関数を返します。 これにより
   、デコレータを重ねたり、"pickle 化" したり、実装ごとに独立した単体
   テストを作成したりできます。

      >>> @fun.register(float)
      ... @fun.register(Decimal)
      ... def fun_num(arg, verbose=False):
      ...     if verbose:
      ...         print("Half of your number:", end=" ")
      ...     print(arg / 2)
      ...
      >>> fun_num is fun
      False

   汎用関数は、呼び出されると 1 つ目の引数の型でディスパッチします:

      >>> fun("Hello, world.")
      Hello, world.
      >>> fun("test.", verbose=True)
      Let me just say, test.
      >>> fun(42, verbose=True)
      Strength in numbers, eh? 42
      >>> fun(['spam', 'spam', 'eggs', 'spam'], verbose=True)
      Enumerate this:
      0 spam
      1 spam
      2 eggs
      3 spam
      >>> fun(None)
      Nothing.
      >>> fun(1.23)
      0.615

   特定の型に対する実装が登録されていない場合、その型のメソッド解決順
   序に従って、より汎用的な実装を探します。 "@singledispatch" でデコレ
   ートした元の関数は、基底型 "object" に対する実装として登録されます
   。 そのため、より適切な実装が見つからなければ元の関数が使われます。

   抽象基底クラス (*abstract base class*) に対して実装が登録されると、
   基底クラスの仮想サブクラスに対してもその実装がディスパッチされます:

      >>> from collections.abc import Mapping
      >>> @fun.register
      ... def _(arg: Mapping, verbose=False):
      ...     if verbose:
      ...         print("Keys & Values")
      ...     for key, value in arg.items():
      ...         print(key, "=>", value)
      ...
      >>> fun({"a": "b"})
      a => b

   指定された型に対して、汎用関数がどの実装を選択するかを確認するには
   、"dispatch()" 属性を使用します:

      >>> fun.dispatch(float)
      <function fun_num at 0x1035a2840>
      >>> fun.dispatch(dict)    # note: default implementation
      <function fun at 0x103fe0000>

   登録されたすべての実装にアクセスするには、読み出し専用の "registry"
   属性を使用します:

      >>> fun.registry.keys()
      dict_keys([<class 'NoneType'>, <class 'int'>, <class 'object'>,
                <class 'decimal.Decimal'>, <class 'list'>,
                <class 'float'>])
      >>> fun.registry[float]
      <function fun_num at 0x1035a2840>
      >>> fun.registry[object]
      <function fun at 0x103fe0000>

   Added in version 3.4.

   バージョン 3.7 で変更: "register()" 属性が型アノテーションの使用を
   サポートしました。

   バージョン 3.11 で変更: "register()" 属性が型アノテーションとして
   "typing.Union" をサポートしました。

class functools.singledispatchmethod(func)

   メソッドを *シングルディスパッチ* *ジェネリック関数* に変換します。

   ジェネリックメソッドを定義するには、"@singledispatchmethod" デコレ
   ータを付けます。 "@singledispatchmethod" でメソッドを定義する場合、
   *self* と *cls* を除いた最初の引数の型に基づいてディスパッチされる
   点に注意してください。

      class Negator:
          @singledispatchmethod
          def neg(self, arg):
              raise NotImplementedError("Cannot negate a")

          @neg.register
          def _(self, arg: int):
              return -arg

          @neg.register
          def _(self, arg: bool):
              return not arg

   "@singledispatchmethod" は "@classmethod" などのデコレータと重ねて
   使えます。 ただし "dispatcher.register" を使うには、
   "singledispatchmethod" が *最も外側* のデコレータでなければなりませ
   ん。 次の "Negator" クラスでは、"neg" メソッドをインスタンスではな
   くクラスに束縛しています。

      class Negator:
          @singledispatchmethod
          @classmethod
          def neg(cls, arg):
              raise NotImplementedError("Cannot negate a")

          @neg.register
          @classmethod
          def _(cls, arg: int):
              return -arg

          @neg.register
          @classmethod
          def _(cls, arg: bool):
              return not arg

   "@staticmethod"、"@~abc.abstractmethod" など、同様のデコレータにも
   この方法を使えます。

   Added in version 3.8.

   バージョン 3.15 で変更: *descriptor* ではない呼び出し可能オブジェク
   トのサポートが追加されました。

functools.update_wrapper(wrapper, wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)

   *wrapper* 関数を更新し、*wrapped* 関数と同じ属性を持つようにします
   。 省略可能な引数はタプルで、元の関数のどの属性をラッパー関数の同名
   の属性に直接代入するか、またラッパー関数のどの属性を元の関数の同名
   の属性で更新するかを指定します。 これらの引数のデフォルト値はモジュ
   ールレベルの定数 "WRAPPER_ASSIGNMENTS" と "WRAPPER_UPDATES" です。
   前者はラッパー関数の "__module__"、"__name__"、"__qualname__"、
   "__annotations__"、"__type_params__"、およびドキュメンテーション文
   字列 "__doc__" に代入し、後者は "__dict__" (インスタンスの辞書) を
   更新します。

   内観などの目的で元の関数にアクセスできるように (例えば "@lru_cache"
   のようなキャッシュ用デコレータを回避できるように)、この関数はラッパ
   ーに "__wrapped__" 属性を自動的に追加します。 この属性はラップされ
   た元の関数を参照します。

   この関数は主に関数を包んでラッパーを返す *デコレータ* 関数の中で使
   われるよう意図されています。もしラッパー関数がアップデートされない
   とすると、返される関数のメタデータは元の関数の定義ではなくラッパー
   関数の定義を反映してしまい、これは通常あまり有益ではありません。

   "update_wrapper()" は、関数以外の呼び出し可能オブジェクトにも使えま
   す。 *assigned* または *updated* で指名され、ラップされるオブジェク
   トに存在しない属性は、すべて無視されます (すなわち、ラッパー関数に
   それらの属性を設定しようとは試みられません)。しかし、 *updated* で
   指名された属性がラッパー関数自身に存在しないなら "AttributeError"
   が送出されます。

   バージョン 3.2 で変更: "__wrapped__" 属性が自動的に追加されるように
   なりました。 "__annotations__" 属性がデフォルトでコピーされるように
   なりました。 属性が欠けていても "AttributeError" を送出しなくなりま
   した。

   バージョン 3.4 で変更: ラップされた関数が "__wrapped__" を定義して
   いる場合でも、 "__wrapped__" が常にラップされた関数を参照するように
   なりました。 (bpo-17482 を参照)

   バージョン 3.12 で変更: "__type_params__" 属性がデフォルトでコピー
   されるようになりました。

@functools.wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)

   これはラッパー関数を定義するときに "update_wrapper()" を関数デコレ
   ータとして呼び出す便宜関数です。これは "partial(update_wrapper,
   wrapped=wrapped, assigned=assigned, updated=updated)" と等価です。
   例えば:

      >>> from functools import wraps
      >>> def my_decorator(f):
      ...     @wraps(f)
      ...     def wrapper(*args, **kwds):
      ...         print('Calling decorated function')
      ...         return f(*args, **kwds)
      ...     return wrapper
      ...
      >>> @my_decorator
      ... def example():
      ...     """Docstring"""
      ...     print('Called example function')
      ...
      >>> example()
      Calling decorated function
      Called example function
      >>> example.__name__
      'example'
      >>> example.__doc__
      'Docstring'

   このデコレータファクトリを使わなければ、例の関数の名前は
   "'wrapper'" になり、元の "example()" のドキュメンテーション文字列は
   失われていたはずです。


"partial" オブジェクト
======================

"partial" オブジェクトは、 "partial()" 関数によって作られる呼び出し可
能オブジェクトです。オブジェクトには読み出し専用の属性が三つあります:

partial.func

   呼び出し可能オブジェクトまたは関数です。 "partial" オブジェクトの呼
   び出しは新しい引数とキーワードと共に "func" に転送されます。

partial.args

   最左の位置引数で、 "partial" オブジェクトの呼び出し時にその呼び出し
   の際の位置引数の前に追加されます。

partial.keywords

   "partial" オブジェクトの呼び出し時に渡されるキーワード引数です。

"partial" オブジェクトは、呼び出し可能で、弱参照でき、属性を持てるとい
う点で 関数オブジェクト に似ています。 ただし重要な違いもあります。 例
えば "__name__" と "__doc__" 属性は自動的には作成されません。
