functools.reduce()
functools.reduce() は「イテラブルの各要素に演算を連続的に作用させて1つの値に集約させる」高階関数 です。
functools.reduce(function, iterable[, initializer])
最初に functoolsモジュールから reduce()関数を、operatorモジュールから関数形式の標準演算子をインポートしておきます。
# PYTHON_REDUCE
# In[1]
# functoolsモジュールをインポート
from functools import reduce
# operatorモジュールから関数形式の標準演算子をインポート
from operator import add, sub, mul, truediv
operator.add(), operator.sub(), operator.mul(), operator.truediv() は、それぞれ算術演算子 +, -, *, / に対応する関数形式の演算子です(関数の引数に足し算や引き算などの演算機能を渡したいときに使用します)。reduce()を用いた簡単な演算例を見てみましょう。
# In[2]
# リストxを定義
x = [1, 2, 3, 4, 5]
# xの要素を順番に足し合わせる
y = reduce(add, x)
print(y)
15
reduce(add, x) は x の各要素に順次 add()関数を作用させます。
つまり、x の要素を合計しています。これは組み込み関数 sum() と同じなので、わざわざこのような面倒なことをする必要性を実感できませんが、reduce() を使うと「要素を順に引き算する」という演算も実行できます。
# In[3]
# リストxを定義
x = [100, 10, 10, 10, 10]
# 最初の要素から2番目以降の要素を引き算する
# 100-10-10-10-10
y = reduce(sub, x)
print(y)
60
同様に「要素を順に掛ける」「要素を順に割る」こともできます。
# In[4]
# リストxを定義
x = [100, 2, 5, 2]
# y = 100×2×5×2
y = reduce(mul, x)
# z = 100÷2÷5÷2
z = reduce(truediv, x)
print("y = {}".format(y))
print("z = {}".format(z))
y = 2000 z = 5.0
reduce() の第 3 引数 initializer で演算の初期値を指定することができます。
# In[5]
# リストxを定義
x = [1, 2, 3, 4, 5]
# 初期値10にxの要素を順番に足し合わせる
# 10+1+2+3+4+5
y = reduce(add, x, 10)
print(y)
25
関数形式の演算子の代わりに lambda式 を使うこともできます。
# In[6]
# リストxを定義
x = [1, 2, 3, 4, 5]
# xの要素を順番に足し合わせる
y = reduce(lambda a, b : a + b, x)
print(y)
15
functools.reduce() の演算手順をもう少し詳しく見ておきましょう。
第 1 引数 function は 2 つの引数を受け取ることのできる関数オブジェクトでなければなりません。たとえば、組み込み関数 pow(a, b) は a**b を返すので、この条件を満たしています。functools.reduce() の第 2 引数に x = [2, 2, 3, 3] というリストを渡したとすると、まず第 1 要素と第 2 要素を使って 2**2 を計算します。その次に (2**2) と 3 を pow() に渡して (2**2)**3 を計算し、最後に (2**2)**3 と 3 を pow() に渡して、((2**2)**3)**3 を計算します。つまり、2**2**3**3 を計算することになります。
# In[7]
# リストxを定義
x = [2, 2, 3, 3]
# y=2**2**3**3
y = reduce(pow, x)
print(y)
262144
このような処理を「畳み込み演算」とよぶこともあります。
ChatGPTがfunctools.reduceを説明します
functools.reduceはPythonのモジュールfunctoolsに含まれる関数の一つです。この関数は、イテラブル(リストやタプルなどの連続した要素を持つオブジェクト)と二項演算子(たとえば加算や乗算)を受け取り、イテラブル内の要素を順番に二項演算子で結合していくことで、単一の値を返します。具体的には、functools.reduceは与えられたイテラブルの最初の2つの要素を取り、それらを二項演算子で結合します。次に、結果と次の要素を二項演算子で結合し、さらにその結果と次の要素を二項演算子で結合し続けます。このプロセスをイテラブルの要素が尽きるまで続けます。以下に例を示します。次のようなリストがあるとします:
◆◆◆◆◆
numbers = [1, 2, 3, 4, 5]
◆◆◆◆◆
functools.reduceを使ってこのリストの要素を加算していくことで、合計値を計算することができます。具体的なコードは次のようになります:
◆◆◆◆◆
import functools
numbers = [1, 2, 3, 4, 5]
total = functools.reduce(lambda x, y: x + y, numbers)
print(total)
# 5
◆◆◆◆◆
この例では、最初に1と2を加算し3が得られ、次に3と3を加算し6が得られ、さらに6と4を加算し10が得られ、最後に10と5を加算して合計値15となります。functools.reduceの第一引数には、二項演算子を指定するための関数(またはラムダ式)を渡します。この関数は2つの引数を受け取り、それらを結合して結果を返します。上記の例では、lambda x, y: x + yを使用して加算を行っていますが、他の演算子を使用することもできます。functools.reduceは、イテラブル内の要素を結合するために便利な関数です。要素の合計や積、最大値や最小値の検索など、複数の要素を結合して単一の値を得る場合に使用することができます。ただし、Python 3ではreduce関数はfunctoolsモジュールに移動されたため、import functoolsが必要です。