St_Hakky’s blog

Data Science / Human Resources / Web Applicationについて書きます

【Python】functools.partial()で関数やメソッドの引数の一部を固定する部分適用を行う

こんにちは。

最近、化粧のやり方とかを紹介するYoutuberを見て、「へぇー綺麗にできるもんだなぁ」って感心している私ですが、今日はfunctools.partial()の綺麗な使い方を見つけたので、その紹介をメモがてらしようと思います。

関数やメソッドの引数の一部を固定させておきたい気持ちがある

関数やメソッドの引数の一部を固定させて、可変な引数のみを与えることができる新しい関数を作りたい時があります(たぶん)。

例えば、map関数で使う関数の一部の引数を固定させておきたい場合とかがそうです。

from functools import partial

def add_func(a, b):
    return a + b

add_list = list(map(partial(add_func, b=5), [0,1,2,3,4,5]))

print(add_list)

他にも色々例はあると思いますが、以下の例がとてもしっくりきました。

参考になる使い方

SVDっていう手法を使って欠損値補完をするアルゴリズムを書いていた時に調べ物をしていて見つけたコードの中にこんなものがありました。

import numpy as np
from scipy.sparse.linalg import svds
from functools import partial

if k is None:
    svdmethod = partial(np.linalg.svd, full_matrices=False)
else:
    svdmethod = partial(svds, k=k)


これを見た時に、「あっ、こうやって使うと便利やなー」と初めてちゃんとした*1functools.partial()の使い方にあった気持ちになりました。

この関数では kの値に応じて関数の引数の一部を固定し、なおかつ違う関数であるものをまとめてラッパーを作っています。

こうすることで、kの条件によって、異なる引数の指定の仕方をするnp.linalg.svdsvdsを一つの関数にまとめ、その後の処理を svdmethodで行えるようにしています。

これは凄い便利ですね。

functools.partial()の使い方

例で挙げたとおりなんですけど、

new_wrapper_func = functools.partial(func, parameter=value)

みたいな感じで、第一引数にベースとなる関数、第二引数以降に固定したい引数を指定することで使うことができます。

固定したい引数が2つ以上ある場合も、以下みたく指定することができます。

from functools import partial

def add_func(a, b, c):
    return a + b + c

add_list = list(map(partial(add_func, b=5, c=3), [0,1,2,3,4,5]))

print(add_list)


使い方自体はそんなに難しくないですね。それでは。

*1:今までちゃんと使っていなかっただけともいえる