partial 関数は、Python の標準ライブラリ(functools モジュール)に 2.5 以降で追加され、カリー化パターンと関数への引数の部分適用を実現するために設計されました。partialmethod は 3.4 以降にクラスメソッドに対して同様の用途で追加されました。
実際のプロジェクトでは、関数に対して一部の引数を固定し、「記憶」された引数の新しい関数を得るというニーズがよく発生します。これはコールバック、引数のテンプレート、特に関数型プログラミングや特定の関数スタイルを期待する API の使用時にコードの可読性を高めるのに便利です。
partial 関数は、与えられた引数の一部を「ハードコーディング」した新しい関数オブジェクトを返します。partialmethod は、クラスメソッドに対して同様のアプローチを実現し、self/cls の引数の取り扱いを正しくサポートします。
コード例:
from functools import partial, partialmethod def power(base, exponent): return base ** exponent # 指数を 2 に固定 square = partial(power, exponent=2) print(square(5)) # 25 class Math: def power(self, base, exponent): return base ** exponent square = partialmethod(power, exponent=2) m = Math() print(m.square(5)) # 25
主な特徴:
partial をクラスメソッドに適用することで、partialmethod と同様に使うことができますか?
いいえ、partial は self/cls を正しく処理せず、クラスメソッドに適用すると期待される動作をしません。self は自動的に置き換えられません。
class C: def m(self, x, y): return x + y wrong = partial(m, y=2) # 間違い!
c.wrong(5) を呼び出した場合、self が自動的に渡されないため、TypeError が発生します。
partial 経由で作成されたオブジェクトは関数ですか?
はい、partial の結果は関数のように振る舞うオブジェクトですが、通常の関数ではなく、call プロトコルを実装した partial クラスのオブジェクトです。
from functools import partial f = partial(pow, 2) print(type(f)) # <class 'functools.partial'>
partial は関数のデフォルト引数で機能しますか?
はい、partial は内部関数のデフォルト値を「上書き」できます。partial に渡された引数は、関数のデフォルト値よりも優先されます。ただし、値が重複しないように注意が必要で、そうしないとエラーになります。
開発者がクラスメソッドの代わりに partialmethod の代わりに partial を適用:
class MyClass: def f(self, x, y): ... squared = partial(f, y=2) ... obj = MyClass() obj.squared(5) # TypeError: 1 つの引数 'self' が不足しています。
利点:
欠点:
その代わりに partialmethod を使用:
from functools import partialmethod class MyClass: def f(self, x, y): return x + y squared = partialmethod(f, y=2) obj = MyClass() print(obj.squared(5)) # 7
利点:
欠点: