Blow Up by Black Swan

Python-2次元の配列処理などに便利なfunctoolsモジュールのpartialメソッド

今回は、flaskのsessionの仕組みを調べている時に出会った、functoolsモジュールのpartialメソッドについてまとめました。2つのシーケンス(リスト)の各値を総当たりで処理したい場合などに便利なメソッドだと思います。実行環境は以下になります。

この記事が参考になりましたら、幸いです。

1. functoolsモジュールとpartialメソッド

functoolsモジュールは、主に高階関数に関するモジュールです。functoolsモジュールでは、reduceメソッドが特に有名だと思います。高階関数については以前記事を執筆していますので、そちらを参考にして頂ければと思います。

このfunctoolsモジュールのpartialメソッドは、ある関数とその一部の引数を部分適用した新たな関数オブジェクト(partialオブジェクト)を生成します。この説明だとなにやら難しく聞こえますが、簡単に言えばある関数が2つ引数を取る場合、片方の引数は固定して、もう1つの引数をいじれるようにするということです。一部の引数を固定することで2つの配列の各値をfor文を使って総当たりで検証、処理する場合などに使い勝手が良いと思います。次の章で具体的なコード例を紹介していきます。

2. コード例

ここからはコード例とともに解説します。

2-1. コード例①

まずは、1つ目のコード例です。基本的な挙動がわかるよう、簡単なコードを作ってみました。

# 基本
from functools import partial

# 基本関数
def times(a, b):
    return a * b

# 実行関数
def main(args):

    # partialオブジェクトの生成
    tentimes = partial(times, b=10)

    print(type(tentimes))
    return tentimes(args)
main(3)

# 戻り値
<class 'functools.partial'>
[12]: 30

このコード例では、基本となる関数はtimes関数になり、このtimes関数はabの2つの関数を取ります。これをmain関数内でpartial関数がラップしています。partial関数は第1引数は対象とする関数オブジェクト、第2引数でその関数オブジェクトの引数を指定します。この時、キーワードを指定した場合はは基本関数のキーワード引数にその値が挿入され、単なる引数が指定された場合は基本関数の第1引数に挿入されます。上記の例では、partial関数の引数でb=10と指定しているので、times関数の第2引数bが10に固定されます。もしpartial(times, 10)と記述した場合は,times関数の引数aが10に固定されるということになります。なお、変数tentimespartialオブジェクトですが、いわば関数オブジェクトのようなものだと言えるでしょう。main関数の実行結果は上記のように30となります。

2-2. コード例②

2つ目のコード例です。

from functools import partial

def times(a, b):
    return a * b

def main():
    nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    tentimes = partial(times, 10)
    return list(map(tentimes, nums))
main()

# 戻り値
[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]

2次元配列ではないですが、times関数の片方の引数を固定することで、リストの各値への総当たり処理を行なっています。リストが2つある場合などはpartial関数は非常に便利だと思います。

3. 最後に

以上ががfunctoolsモジュールのpartialメソッドです。知名度は低いメソッドですが、知っているだけでかなりコードを書くのが楽になるメソッドだと思います。このような便利なメソッドをどんどん活用していくことで、コードの可読性やクオリティは上がっていくのかなと思います。読んでいただき、ありがとうございました。