これは何?
mapについてpythonの公式ドキュメント1見ていたとき
map() と starmap() の違いは function(a,b) と function(*c) の差に似ています。
という記述があり、何だコレってなったのがきっかけ。
function(a,b) と function(*c) の差
を知るのが目的
アスタリスク引数の効果
Qiita記事2にすごくよくまとまっていた。
function(a,b) と function(*c) の差と言っているのが、以下のうちどちらかわからない。
def sum1(a,b):
return a+b
def sum2(*c):
ret = 0
for n in c:
ret += n
return ret
a = 1
b = 2
c = [a,b]
sum1(a,b)
# > 3
# pattern1
sum1(*c)
# > 3
# pattern2
sum2(*c)
# > 3
pattern1はアンパックであり、
sum1(*c) = sum1(c[0], c[1])
で、len(c) = 2
だから(sum1の引数の数と一致するから)うまく動く。
pattern2は可変長の引数に対する処理で、
len(c)
がいくつであってもうまく動く。
関数の*引数についてはよくわかったが、せっかくなので、starmap()について見てみる。
itertools.startmap()
公式ドキュメント1にあるように
list(starmap(pow, [[2,3],[3,4],[4,5]]))
# --> 32 9 1000
となる。
これは$2^{3}, 3^{4}, 4^{5}$のように
第2引数、$[a,b,c,\cdots]$に対して
$a[0]^{a[1]},b[0]^{b[1]},c[0]^{c[1]}, \cdots$を計算していることがわかる。
同じように
list(starmap(sum, [[2,3],[3,4],[4,5]]))
とすれば、$2+3, 3+4, 4+5$を計算してくれるだろうと思っていたが
TypeError: 'int' object is not iterable
と出てくる。
int object…?
list(starmap(sum, [[2,3,4],[3,4,5],[4,5,6]]))
とすると
TypeError: sum() takes at most 2 arguments (3 given)
だと…。
なるほど、3 givenということは、2, 3, 4の3つを引数だと思ったのか。
sum([2,3,4])ではなく、sum(2,3,4)として扱われたということか。
[2,3]のときも
sum(2,3)として扱われて、第1引数が2でintが入っていたため
TypeError: 'int' object is not iterable
このErrorが出たのか。
公式ドキュメント3によるとPython3.8以降では
sum(iterable, /, start=0)
らしくて、第2引数で下駄を履かせられるようになったらしい。
話をもとに戻して、$2+3, 3+4, 4+5$とを計算するためには
list(starmap(sum, [[[2,3]],[[3,4]],[[4,5]]]))
# [5, 7, 9]
とすれば良い。
つまりstarmapは
starmap(func, [funcに入れる引数, funcに入れる引数,...])
と理解すれば良さそう