業務で zip 関数を使うことがあり、まだ理解が足りない点が多いのでアウトプットして知識を深めていく。
zip 関数とは
Python の組み込み関数の 1 つで、import 文不要で動作する。複数のイテラブルから tuple を生成する。
>>> for item in zip([1, 2, 3], ['sugar', 'spice', 'everything nice']): ... print(item) ... (1, 'sugar') (2, 'spice') (3, 'everything nice')
zip 関数の返り値の型は zip 型となる。また zip 関数は遅延評価のため、変数に代入して処理されることはないようだ。基本 for ループ内で処理したり list でラップする必要があると考えた方がよさそう。
>>> value = zip([1, 2, 3], ['sugar', 'spice', 'everything nice']) >>> print(value) <zip object at 0x104d2d7c0> >>> type(value) <class 'zip'> >>> dict(value) {}
zip() は遅延評価です: イテラブルが for ループに渡されたり、 list でラップされたりするなどして反復処理されるまで、要素が実際に処理されることはありません。
Key-Value な形に加工することもできそう。
>>> for k, v in zip([1, 2, 3], ['sugar', 'spice', 'everything nice']): ... print(k, v) ... 1 sugar 2 spice 3 everything nice >>> dict(zip([1, 2, 3], ['sugar', 'spice', 'everything nice'])) {1: 'sugar', 2: 'spice', 3: 'everything nice'}
イテラブルってなんだっけ
以下の記事が参考になった。list や tuple を使うケースが多そう。
zip 関数で渡されたイテラブルの要素数が異なる場合の挙動
第 1 引数の要素数は 4, 第 2 引数の要素数が 3 の場合、第 1 引数の 4 番目の要素が無視される。
>>> for item in zip([1, 2, 3, 4], ['sugar', 'spice', 'everything nice']): ... print(item) ... (1, 'sugar') (2, 'spice') (3, 'everything nice')
逆に第 1 引数の要素数を 3, 第 2 引数の要素数を 4 とした場合、第 2 引数の 4 番目の要素が無視される。
>>> for item in zip([1, 2, 3], ['sugar', 'spice', 'everything nice', 'bad']): ... print(item) ... (1, 'sugar') (2, 'spice') (3, 'everything nice')
これはドキュメントに記載の通り。
デフォルトでは、 zip() は最も短いイテラブルが消費しきった時点で停止します。より繰り返し数の長いイテラブルの残りの要素は無視して、結果を最も短いイテラブルの長さに切り詰めます:
要素数が異なる場合はエラーとさせたい場合は strict=True
オプションを付与することで ValueError
を 出すことができる。
>>> for item in zip([1, 2, 3], ['sugar', 'spice', 'everything nice', 'bad'], strict=True): ... print(item) ... (1, 'sugar') (2, 'spice') (3, 'everything nice') Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: zip() argument 2 is longer than argument 1