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

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

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

"functools" モジュールは高階関数、つまり関数に影響を及ぼしたり他の関数
を返したりする関数のためのものです。一般に、どんな呼び出し可能オブジェ
クトでもこのモジュールの目的には関数として扱えます。

モジュール "functools" は以下の関数を定義します:

@functools.cache(user_function)

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

   Returns the same as "lru_cache(maxsize=None)", creating a thin
   wrapper around a dictionary lookup for the function arguments.
   Because it never needs to evict old values, this is smaller and
   faster than "lru_cache()" with a size limit.

   例えば:

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

      >>> factorial(10)      # no previously cached result, makes 11 recursive calls
      3628800
      >>> factorial(5)       # just looks up cached value result
      120
      >>> factorial(12)      # makes two new recursive calls, the other 10 are cached
      479001600

   The cache is threadsafe so that the wrapped function can be used in
   multiple threads.  This means that the underlying data structure
   will remain coherent during concurrent updates.

   It is possible for the wrapped function to be called more than once
   if another thread makes an additional call before the initial call
   has been completed and cached.

   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()" とやや異なります。通常
   のプロパティは、セッター (setter) が定義されない限り書き込みを禁止
   します。対照的に、 *cached_property* は書き込みを許します。

   *cached_property* デコレータはルックアップテーブルで、同名の属性が
   存在しない場合のみ動作します。動作した場合、 *cached_property* は同
   名の属性に書き込みを行います。その後の属性の読み込みと書き込みは
   *cached_property* メソッドより優先され、通常の属性のように働きます
   。

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

   The *cached_property* does not prevent a possible race condition in
   multi-threaded usage. The getter function could run more than once
   on the same instance, with the latest run setting the cached value.
   If the cached property is idempotent or otherwise not harmful to
   run more than once on an instance, this is fine. If synchronization
   is needed, implement the necessary locking inside the decorated
   getter function or around the cached property access.

   このデコレータは **PEP 412** のキー共有辞書のインターフェースを持ち
   ます。これは、インスタンス辞書がより多くのスペースを使う可能性があ
   ることを意味します。

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

   If a mutable mapping is not available or if space-efficient key
   sharing is desired, an effect similar to "cached_property()" can
   also be achieved by stacking "property()" on top of "lru_cache()".
   See メソッド呼び出しをキャッシュするには どうしたらいいですか？ for
   more details on how this differs from "cached_property()".

   Added in version 3.8.

   バージョン 3.12 で変更: Prior to Python 3.12, "cached_property"
   included an undocumented lock to ensure that in multi-threaded
   usage the getter function was guaranteed to run only once per
   instance. However, the lock was per-property, not per-instance,
   which could result in unacceptably high lock contention. In Python
   3.12+ this locking is removed.

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))  # locale-aware sort order

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

   Added in version 3.2.

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

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

   The cache is threadsafe so that the wrapped function can be used in
   multiple threads.  This means that the underlying data structure
   will remain coherent during concurrent updates.

   It is possible for the wrapped function to be called more than once
   if another thread makes an additional call before the initial call
   has been completed and cached.

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

   引数のパターンが異なる場合は、異なる呼び出しと見なされ別々のキャッ
   シュエントリーとなります。 例えば、 "f(a=1, b=2)" と "f(b=2, a=1)"
   はキーワード引数の順序が異なっているので、2つの別個のキャッシュエン
   トリーになります。

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

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

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

   If *typed* is set to true, function arguments of different types
   will be cached separately.  If *typed* is false, the implementation
   will usually regard them as equivalent calls and only cache a
   single result. (Some types such as *str* and *int* may be cached
   separately even when *typed* is false.)

   Note, type specificity applies only to the function's immediate
   arguments rather than their contents.  The scalar arguments,
   "Decimal(42)" and "Fraction(42)" are be treated as distinct calls
   with distinct results. In contrast, the tuple arguments "('answer',
   Decimal(42))" and "('answer', Fraction(42))" are treated as
   equivalent.

   The wrapped function is instrumented with a "cache_parameters()"
   function that returns a new "dict" showing the values for *maxsize*
   and *typed*.  This is for information purposes only.  Mutating the
   values has no effect.

   To help measure the effectiveness of the cache and tune the
   *maxsize* parameter, the wrapped function is instrumented with a
   "cache_info()" function that returns a *named tuple* showing
   *hits*, *misses*, *maxsize* and *currsize*.

   The decorator also provides a "cache_clear()" function for clearing
   or invalidating the cache.

   元々の基底の関数には、 "__wrapped__" 属性を通してアクセスできます。
   これはキャッシュを回避して、または関数を別のキャッシュでラップして
   、内観するのに便利です。

   The cache keeps references to the arguments and return values until
   they age out of the cache or until the cache is cleared.

   If a method is cached, the "self" instance argument is included in
   the cache.  See メソッド呼び出しをキャッシュするには どうしたらいい
   ですか？

   An LRU (least recently used) cache works best when the most recent
   calls are the best predictors of upcoming calls (for example, the
   most popular articles on a news server tend to change each day).
   The cache's size limit assures that the cache does not grow without
   bound on long-running processes such as web servers.

   In general, the LRU cache should only be used when you want to
   reuse previously computed values.  Accordingly, it doesn't make
   sense to cache functions with side-effects, functions that need to
   create distinct mutable objects on each call (such as generators
   and async functions), or impure functions such as time() or
   random().

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

      @lru_cache(maxsize=32)
      def get_pep(num):
          'Retrieve text of a 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 で変更: Added the function "cache_parameters()"

@functools.total_ordering

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

   The class must define one of "__lt__()", "__le__()", "__gt__()", or
   "__ge__()". In addition, the class should supply an "__eq__()"
   method.

   例えば:

      @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 つの拡張比較メ
     ソッドをすべて実装すれば、簡単にスピードアップを図れるでしょう。

   注釈:

     This decorator makes no attempt to override methods that have
     been declared in the class *or its superclasses*. Meaning that if
     a superclass defines a comparison operator, *total_ordering* will
     not implement it again, even if the original method is abstract.

   Added in version 3.2.

   バージョン 3.4 で変更: Returning "NotImplemented" from the
   underlying comparison function for unrecognised types is now
   supported.

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

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

      def partial(func, /, *args, **keywords):
          def newfunc(*fargs, **fkeywords):
              newkeywords = {**keywords, **fkeywords}
              return func(*args, *fargs, **newkeywords)
          newfunc.func = func
          newfunc.args = args
          newfunc.keywords = keywords
          return newfunc

   The "partial()" is used for partial function application which
   "freezes" some portion of a function's arguments and/or keywords
   resulting in a new object with a simplified signature.  For
   example, "partial()" can be used to create a callable that behaves
   like the "int()" function where the *base* argument defaults to
   two:

   >>> from functools import partial
   >>> basetwo = partial(int, base=2)
   >>> basetwo.__doc__ = 'Convert base 2 string to an int.'
   >>> basetwo('10010')
   18

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

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

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

   When *func* is a descriptor (such as a normal Python function,
   "classmethod()", "staticmethod()", "abstractmethod()" or another
   instance of "partialmethod"), calls to "__get__" are delegated to
   the underlying descriptor, and an appropriate partial object
   returned as the result.

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

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

      >>> 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, ]/)

   Apply *function* of two arguments cumulatively to the items of
   *iterable*, from left to right, so as to reduce the iterable to a
   single value.  For example, "reduce(lambda x, y: x+y, [1, 2, 3, 4,
   5])" calculates "((((1+2)+3)+4)+5)". The left argument, *x*, is the
   accumulated value and the right argument, *y*, is the update value
   from the *iterable*.  If the optional *initial* is present, it is
   placed before the items of the iterable in the calculation, and
   serves as a default when the iterable is empty.  If *initial* is
   not given and *iterable* contains only one item, the first item is
   returned.

   およそ次と等価です:

      initial_missing = object()

      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()" を
   参照してください。

@functools.singledispatch

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

   To define a generic function, decorate it with the
   "@singledispatch" decorator. When defining a function using
   "@singledispatch", note that the dispatch happens on the type of
   the first argument:

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

   To add overloaded implementations to the function, use the
   "register()" attribute of the generic function, which can be used
   as a decorator.  For functions annotated with types, the decorator
   will infer the type of the first argument automatically:

      >>> @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)

   "types.UnionType" and "typing.Union" can also be used:

      >>> @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)
      ...

   For code that dispatches on a collections type (e.g., "list"), but
   wants to typehint the items of the collection (e.g., "list[int]"),
   the dispatch type should be passed explicitly to the decorator
   itself with the typehint going into the function definition:

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

   注釈:

     At runtime the function will dispatch on an instance of a list
     regardless of the type contained within the list i.e. "[1,2,3]"
     will be dispatched the same as "["foo", "bar", "baz"]". The
     annotation provided in this example is for static type checkers
     only and has no runtime impact.

   To enable registering *lambdas* and pre-existing functions, the
   "register()" attribute can also be used in a functional form:

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

   The "register()" attribute returns the undecorated function. This
   enables decorator stacking, "pickling", and the creation of unit
   tests for each variant independently:

      >>> @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 で変更: The "register()" attribute now supports
   using type annotations.

   バージョン 3.11 で変更: The "register()" attribute now supports
   "types.UnionType" and "typing.Union" as type annotations.

class functools.singledispatchmethod(func)

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

   To define a generic method, decorate it with the
   "@singledispatchmethod" decorator. When defining a function using
   "@singledispatchmethod", note that the dispatch happens on the type
   of the first non-*self* or non-*cls* argument:

      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", "@abstractmethod" など。

   Added in version 3.8.

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

   Update a *wrapper* function to look like the *wrapped* function.
   The optional arguments are tuples to specify which attributes of
   the original function are assigned directly to the matching
   attributes on the wrapper function and which attributes of the
   wrapper function are updated with the corresponding attributes from
   the original function. The default values for these arguments are
   the module level constants "WRAPPER_ASSIGNMENTS" (which assigns to
   the wrapper function's "__module__", "__name__", "__qualname__",
   "__annotations__", "__type_params__", and "__doc__", the
   documentation string) and "WRAPPER_UPDATES" (which updates the
   wrapper function's "__dict__", i.e. the instance dictionary).

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

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

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

   バージョン 3.2 で変更: The "__wrapped__" attribute is now
   automatically added. The "__annotations__" attribute is now copied
   by default. Missing attributes no longer trigger an
   "AttributeError".

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

   バージョン 3.12 で変更: The "__type_params__" attribute is now
   copied by default.

@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'

   Without the use of this decorator factory, the name of the example
   function would have been "'wrapper'", and the docstring of the
   original "example()" would have been lost.


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

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

partial.func

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

partial.args

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

partial.keywords

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

"partial" objects are like function objects in that they are callable,
weak referenceable, and can have attributes. There are some important
differences.  For instance, the "__name__" and "function.__doc__"
attributes are not created automatically.  Also, "partial" objects
defined in classes behave like static methods and do not transform
into bound methods during instance attribute look-up.
