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

バージョン 2.5 で追加.

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

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

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

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

functools.cmp_to_key(func)

   古いスタイルの比較関数を *key function* に変換します。 key 関数を受
   け取る関数 ("sorted()", "min()", "max()", "heapq.nlargest()",
   "heapq.nsmallest()", "itertools.groupby()" など) と共に使用します。
   この関数は、主に比較関数をサポートしていない Python 3 への移行のた
   めのツールとして用意されています。

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

   例:

      sorted(iterable, key=cmp_to_key(locale.strcoll))  # locale-aware sort order

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

   バージョン 2.7 で追加.

functools.total_ordering(cls)

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

   引数のクラスは、 "__lt__()", "__le__()", "__gt__()", "__ge__()" の
   中からどれか1つと、 "__eq__()" メソッドを定義する必要があります。

   例えば:

      @total_ordering
      class Student:
          def __eq__(self, other):
              return ((self.lastname.lower(), self.firstname.lower()) ==
                      (other.lastname.lower(), other.firstname.lower()))
          def __lt__(self, other):
              return ((self.lastname.lower(), self.firstname.lower()) <
                      (other.lastname.lower(), other.firstname.lower()))

   バージョン 2.7 で追加.

functools.reduce(function, iterable[, initializer])

   これは "reduce()" 関数と同じものです。このモジュールからも使えるよ
   うにしたのは Python 3 と前方互換なコードを書けるようにするためです
   。

   バージョン 2.6 で追加.

functools.partial(func[,*args][, **keywords])

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

      def partial(func, *args, **keywords):
          def newfunc(*fargs, **fkeywords):
              newkeywords = keywords.copy()
              newkeywords.update(fkeywords)
              return func(*(args + fargs), **newkeywords)
          newfunc.func = func
          newfunc.args = args
          newfunc.keywords = keywords
          return newfunc

   関数 "partial()" は、関数の位置引数・キーワード引数の一部を「凍結」
   した部分適用として使われ、簡素化された引数形式をもった新たなオブジ
   ェクトを作り出します。例えば、 "partial()" を使って *base* 引数のデ
   フォルトが 2 である "int()" 関数のように振る舞う呼び出し可能オブジ
   ェクトを作ることができます:

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

functools.update_wrapper(wrapper, wrapped[, assigned][, updated])

   *wrapper* 関数を *wrapped* 関数に見えるようにアップデートします。オ
   プション引数はタプルで、元の関数のどの属性がラッパ関数の対応する属
   性に直接代入されるか、またラッパ関数のどの属性が元の関数の対応する
   属性でアップデートされる(updated)か、を指定します。これらの引数のデ
   フォルト値はモジュールレベル定数 *WRAPPER_ASSIGNMENTS* (ラッパ関数
   の *__name__* 、*__module__* 、そしてドキュメンテーション文字列
   *__doc__* に代入します) と *WRAPPER_UPDATES* (ラッパ関数の
   *__dict__* 、すなわちインスタンス辞書をアップデートします) です。

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

functools.wraps(wrapped[, assigned][, updated])

   これはラッパ関数を定義するときに "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()" のドキュメンテーション文字列
   は失われたところです。


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

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

partial.func

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

partial.args

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

partial.keywords

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

"partial" オブジェクトは "function" オブジェクトのように呼び出し可能で
、弱参照可能で、属性を持つことができます。重要な相違点もあります。例え
ば、 "__name__" と "__doc__" 両属性は自動では作られません。また、クラ
ス中で定義された "partial" オブジェクトはスタティックメソッドのように
振る舞い、インスタンスの属性問い合わせの中で束縛メソッドに変換されませ
ん。
