pythonにはmapという関数があります。関数型プログラミングに役立ち、大変便利な関数です。
しかし、これはデフォルトでは一つの引数を前提としています。
>>> list(map(lambda a,b: a+b, zip([1,2,3],[4,5,6]))) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: <lambda>() missing 1 required positional argument: 'b'
困ったものですね。こういうときは関数の側で工夫してあげるしかないのでしょうか?
>>> list(map(lambda x: x[0]+x[1], zip([1,2,3],[4,5,6]))) [5, 7, 9]
内包表記使えよ、という考え方もあると思いますが、不問とします。
こういうケースでうまく働くのが、itertools.starmapです。
10.1. itertools — 効率的なループ実行のためのイテレータ生成関数 — Python 3.6.5 ドキュメント
starはunpackingのstar。こう書くともうだいたい察してしまった人もいるでしょうが、こう書けます。
>>> from itertools import starmap >>> list(starmap(lambda a,b: a+b, zip([1,2,3],[4,5,6]))) [5, 7, 9]
引数が格納されたtupleは、lambdaに渡されるときにunpackされる訳です。気が利いてますね。
これと同様にデフォルト引数を渡せるitertools.starstarmapもあります・・・と言いたいところですが、ありませんでした。残念。
それでも内包表記で書きたい人へ
まあ、これのためにimportするくらいなら・・・という気持ちはとてもよくわかりますし、私も普段はそうするクチなんですが。
>>> [a+b for a,b in zip([1,2,3],[4,5,6])] [5, 7, 9]
listとlambdaが端折れる分だけ短く書けているように見えますが、返り値がジェネレータで構わなくて、既存の関数を呼び出したいときはmapの方が短くなる(こともある)ようです。
追記
この記事書いたときはすっかり忘れていたけど、そういえばmapはデフォルトで複数の引数を取れる。
>>> list(map(lambda a,b:a+b, [1,2,3],[4,5,6])) [5, 7, 9]
普通にこっちで良いですね。
zipされたものを入力に渡したいときは工夫が必要だが、unpackしてもう一回zipしてまたunpackすれば良い。
>>> list(map(lambda a,b:a+b, *zip(*zip([1,2,3],[4,5,6])))) [5, 7, 9]