Address
304 North Cardinal St.
Dorchester Center, MA 02124

Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM

Python Zip関数の解説

【初心者向け】PythonのZip関数の解説

Python初心者に向けたzip関数の使い方の解説

今回はPythonの超便利なzip関数の初心者向け解説です。zip関数は基本的には「複数のリストをまとめる」という機能を担当するこが多い関数です。

今回はそんなzip関数について、以下の点を中心に解説をしていきます。

  • zip関数とは何か
  • zip関数の使い方と注意点
  • イテレータとは何か
  • zip関数とenumerate関数を組み合わせる方法

zip関数とは?

まずPythonの公式ドキュメントには次のように説明されています。

zip() returns an iterator of tuples, where the i-th tuple contains the i-th element from each of the argument iterables.

この意味を箇条書きしていきます。

  • タプルのイテレータを返す
  • 返されるタプルがX番目ならば、zip関数の引数となっている各イテラブルのX番目の要素を含む

そして書き方は次のように書かれています。

zip(*iterables, strict=False)

引数であるiterablesはイテラブル(iterable)の複数形なので、イテラブルを2つ以上使うことが基本ということですね。

イテラブルの例で有名なのはリストですね。そのように引数にリストを2つ以上持たせて使うことが多いと思います。したがって、

zip(リスト1, リスト2, リスト3,・・・)

とするのが典型です。

strict=Falseについては今回は省略します。

zip関数の使い方と注意点

リストをzip関数で処理してもリストにならない

ではさっそく具体例を見てみましょう。

names = ['ルイズ', '神楽', 'シャナ']
attribution = ['ツンデレ', 'エセ中華', 'メロンパン']

まずこのように2つのリストを作ります。次にこれらにzip関数を使いましょう。

zipped = zip(names, attribution)

みなさん頭の中のイメージでは次のようになっていることでしょう。

リストインデックスnamesattribution
0ルイズツンデレ
1神楽エセ中華
2シャナメロンパン

そしてできあがったものの型を調べてみましょう。

type(zipped)

こうすると、結果は「zip」と表示されます。つまり、zip関数でリストをまとめてもリストになるわけじゃないのです。ここが要注意です。zipという特殊なものになるのですね。

また、print関数を使ってその中身を表示させようとしても、

print(zipped)

<zip object at 0x0000027326266BC0>

という意味不明な情報が表示されるだけです。

zip関数とイテレータと__next__メソッド

ではどのようにすれば、2つのリストをまとめてzippedの中身を見られるでしょうか。

ここでポイントになるのがzip関数は、イテレータを返すという仕様です。

イテレータとイテラブルの違いについては「【初心者にもわかりやすく】Pythonのイテレータについて、その基本とfor文の仕組みを解説」で解説しました。また見ておいてください。

簡単いえば、イテレータとは、次の2つのメソッドを持っているものです。

  • __iter__
  • __next__

実際にこれらのメソッドを持っているのか確かめてみましょう。組み込み関数のdir()を使います。dir()は引数に指定したオブジェクトの有効な属性のリスト

dir(zipped)

次のように出力されます。

['__class__',
 '__delattr__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__iter__',
 '__le__',
 '__lt__',
 '__ne__',
 '__new__',
 '__next__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__']

きちんと__iter__と__next__メソッドがあることがわかりますね。ここからも、zip関数を使った結果はイテレータになることが確認できます。リストでも辞書でもないデータとなります。

そこで、この__next__メソッドを使ってみましょう。__next__メソッドは「イテレータがもつ連続する手続きを1つだけ処理を進める」というメソッドです。1回につき1つしか処理が進行しません。

zipped.__next__()

次のように出力されます。

('ルイズ', 'ツンデレ')

これは明らかに、

  • リストnamesの0番目
  • リストattributionの0番目

の情報ですね。

再び最初につくったリストnamesとリストattributionの要素一覧をどうぞ。

リストインデックスリストnamesリストattribution
0ルイズツンデレ
1神楽エセ中華
2シャナメロンパン

さて、さらに再び全く同じものを入力してみましょう。

zipped.__next__()

今度は、

  • リストnamesの1番目
  • リストattributionの1番目
('神楽', 'エセ中華')

と出力されました。さらに同じことを続けて、

zipped.__next__()

この結果、

('シャナ', 'メロンパン')

さらに4回目、

zipped.__next__()

とすると、今度は

StopIteration: 

このようなメッセージが出て不具合が出たはずです。これはもう3回目で最後の項目まで行ったからです。4回目では表示すべきものが何もないのでこのようにStopしたと表示されます。

ちなみに、このあとさらに、

zipped.__next__()

と入力しても、結局StopIterationが表示されます。つまり自動的にもとの状態に戻ったりしないので注意してください。

ここまででいちおうはzippedの中身を表示させるということはできましたが、こんなやり方は明らかにめんどくさいですね。そこで次のようにenumerate関数と組み合わせて、zippedの中身を表示させてみましょう。

zip関数の結果の利用法

enumerate関数と組み合わせる

zip関数とよくセットで使われるのが組み込み関数のenumerate関数です。enumerate関数は、引数で指定されたイテラブルの「インデックス」と「その要素」を取得するものです。

ちなみにenumerateという英語は「数え上げる」という意味です。

使い方は次の通りです。

enumerate(iterable, start=0)

という形で使います。なにより大切なのは引数にイテラブルを取るという点ですね。

このイテラブルには3種類ありまして、

  • シーケンス
  • イテレータ
  • イテレーションをサポートするその他のオブジェクト

です。

上述のようにzip関数はイテレータを作って返します。よって問題ありません。さて実際に使ってみましょう。

zipped=zip(names, attribution)
for i, t in enumerate(zipped):
    print(f'インデックスは{i}で、その要素は{t}')

1行目の「zipped=zip(names, attribution)」は、これまで__next__メソッドを使った処理をやっていたので、zippedの中身は空っぽのようになっていますので、ここで改めてzippedの実体をつくっておきます。

この変数iとtには、それぞれ次の情報が入ります。

  • i→インデックスの情報
  • t→リストnamesとリストattributionの各要素を組み合わせたタプル

さてこの結果はこうなります。

インデックスは0で、その要素は('ルイズ', 'ツンデレ')
インデックスは1で、その要素は('神楽', 'エセ中華')
インデックスは2で、その要素は('シャナ', 'メロンパン')

enumerate関数はインデックスとそれに対応する要素を取得するというのをわかってもらえると思います。

listを使ってzip型のオブジェクトの情報を表示

上ではenumerate関数を使って、zip型オブジェクトzippedの中身を表示してみましたが、listを使っても可能です。いろいろやり方はあると思いますが、1番シンプルなのは、

list(zipped)

これで終わりですね。これで、次のように出力されます。

[('ルイズ', 'ツンデレ'), ('神楽', 'エセ中華'), ('シャナ', 'メロンパン')]

ちゃんとリストの表示になっていますね。

また次のようなやり方でもできます。

new_list=[]
for n in range(0, len(names)):
    tuple_obj=names[n], attribution[n]
    new_list.append(tuple_obj)
print(new_list)

こうすると、やはりリストとして、

[('ルイズ', 'ツンデレ'), ('神楽', 'エセ中華'), ('シャナ', 'メロンパン')]

と出力されます。

以上のように複数のリストをまとめて、zip関数によって処理できます。ただし、その結果はあくまでzip型という特殊な型(?)のオブジェクトになるので、そのままでは利用しづらいです。

そこでその結果をまた1つのリストなどにしましょう。そしてその方法は以上のようにいろいろあります。

プログラミングを学びIT業界へ転職するなら現役エンジニアから学べるプログラミングスクールTechAcademy [テックアカデミー]でオンライン講座を受講するのが良いと思います。1人で悩みながら学習を進めるよりもわかりやすく、費やす時間も少なく合理的・効率的に学習できるからです。

など各種の講座が用意されています。無料で体験できるテックアカデミー無料体験も用意されています。

愛を分かち合いましょう