【Python基礎】zip関数、enumerate関数、リスト内包表記

  • URLをコピーしました!
目次

for文

前にfor文の基本的な使い方を紹介しました。

色々勉強してきて、もう少し高度な使い方があることが分かってきたので、まとめてみたいと思います。

その前に「for文」のおさらいからいきましょう。

for文とはあるリストの中の要素を順番に取得する方法でした。

list1 = ["A", "B", "C", "D", "E", "F", "G"]

for l1 in list1:
    print(l1)

実行結果
A
B
C
D
E
F
G

リスト内の要素を一つずつ処理をするのに使われます。

zip関数

前には複数のリストからそれぞれ要素を順番に取得する「zip関数」も紹介しました。

list1 = ["A", "B", "C", "D", "E", "F", "G"]
list2 = ["a", "b", "c", "d", "e", "f", "g"]

for l1, l2 in zip(list1, list2):
    print(l1 + " " + l2)

実行結果
A a
B b
C c
D d
E e
F f
G g

ここでは二つのリストからそれぞれ要素を順番に取得していますが、三つ以上のリストからそれぞれ要素を順番に取り出すことも可能です。

zip関数に関しては紹介しただけでなく、私も好んで使っているので、これまで紹介したプログラムの中で見た方も多いでしょう。

enumerate関数

今回新たに紹介する一つ目の関数は「enumerate関数」です。

このenumerate関数では繰り返しの回数とともにリストから要素を順番に取得することができます。

list1 = ["A", "B", "C", "D", "E", "F", "G"]

for i, l1 in enumerate(list1):
    print(str(i) + " " + l1)

実行結果
0 A
1 B
2 C
3 D
4 E
5 F
6 G

リスト内のインデックス番号や繰り返しの回数を処理の中で使う場合に有効そうな関数です。

これをenumerate関数なしで書くとこうなります。

list1 = ["A", "B", "C", "D", "E", "F", "G"]

i = 0

for l1 in list1:
    print(str(i) + " " + l1)
    i = i + 1

実行結果
0 A
1 B
2 C
3 D
4 E
5 F
6 G

ただし注意する点としてこのenumerate関数だけでは、繰り返しの回数と1つのリストからの要素しか取得できません。

list1 = ["A", "B", "C", "D", "E", "F", "G"]
list2 = ["a", "b", "c", "d", "e", "f", "g"]

for i, l1, l2 in enumerate(list1, list2):
    print(str(i) + " " + l1 + " " + l2)

実行結果
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-13-bb69bb08ce6a> in <module>
----> 1 for i, l1, l2 in enumerate(list1, list2):
      2     print(str(i) + " " + l1 + " " + l2)

TypeError: 'list' object cannot be interpreted as an integer

enumerate関数を使いつつ、複数のリストから要素を順番に取得したい場合は、先の紹介したzip関数と組み合わせます。

この場合、zip関数で順番に取得している要素は一つの変数で受け取りますが、中身はタプルとして取得されます。

list1 = ["A", "B", "C", "D", "E", "F", "G"]
list2 = ["a", "b", "c", "d", "e", "f", "g"]

for i, l in enumerate(zip(list1, list2)):
    print(str(i), l)

実行結果
0 ('A', 'a')
1 ('B', 'b')
2 ('C', 'c')
3 ('D', 'd')
4 ('E', 'e')
5 ('F', 'f')
6 ('G', 'g')

そのためそれぞれの要素を取得したい場合は、インデックスを指定するか、タプルとして受け取ります。

list1 = ["A", "B", "C", "D", "E", "F", "G"]
list2 = ["a", "b", "c", "d", "e", "f", "g"]

for i, l in enumerate(zip(list1, list2)):
    print(str(i) + " " + l[0] + " " + l[1])

実行結果
0 A a
1 B b
2 C c
3 D d
4 E e
5 F f
6 G g
list1 = ["A", "B", "C", "D", "E", "F", "G"]
list2 = ["a", "b", "c", "d", "e", "f", "g"]

for i, (l1, l2) in enumerate(zip(list1, list2)):
    print(str(i) + " " + l1 + " " + l2)

実行結果
0 A a
1 B b
2 C c
3 D d
4 E e
5 F f
6 G g

リスト内包表記

今回もう一つ新たに紹介するのが「リスト内包表記」です。

こちらはfor文を使いつつ、新たなリストを作る時に用いられます。

ちょっと普段は絶対にやらない例にはなってしまいますが、先ほどのlist1から要素を一つずつ取得して、list3に格納するということをやってみましょう。

まずはリスト内包表記を使わない例から。

list1 = ["A", "B", "C", "D", "E", "F", "G"]

list3 = []

for l1 in list1:
    list3.append(l1)
    
print(list3)

実行結果
['A', 'B', 'C', 'D', 'E', 'F', 'G']

次にリスト内包表記を使った場合です。

list1 = ["A", "B", "C", "D", "E", "F", "G"]

list3 = [l1 for l1 in list1]

print(list3)

実行結果
['A', 'B', 'C', 'D', 'E', 'F', 'G']

新たなリストを作るところが1行でかけてしまうというシンプルさとプログラム的にリスト内包表記を使った方が処理が速いというメリットがあるそうです。

ちなみにif文を組み合わせて、条件分岐をさせることもできます。

list1 = ["A", "B", "C", "D", "E", "F", "G"]

list3 = [l1 for l1 in list1 if l1 != "A"]

print(list3)

実行結果
['B', 'C', 'D', 'E', 'F', 'G']

リスト内包表記を使わないとこんな感じでしょうか。

list1 = ["A", "B", "C", "D", "E", "F", "G"]

list3 = []

for l1 in list1:
    if l1 != "A":
        list3.append(l1)

print(list3)

実行結果
['B', 'C', 'D', 'E', 'F', 'G']

さらにif文で条件に合わないものを処理するelseも使うことができます。

list1 = ["A", "B", "C", "D", "E", "F", "G"]

list3 = [l1 if l1 != "A" else "G" for l1 in list1]

print(list3)

実行結果
['G', 'B', 'C', 'D', 'E', 'F', 'G']

ただしif 〜 elseを書く場所に気をつけてください。

上の例で書いたようにifだけの場合はfor文の後に書きますが、if 〜 elseの場合はfor文の前に書きます。

ifだけの場合、for文の前に書いてしまうとエラーが出ます。

list1 = ["A", "B", "C", "D", "E", "F", "G"]

list3 = [l1 if l1 != "A" for l1 in list1]

print(list3)

実行結果
  File "<ipython-input-51-99f3f32fbb15>", line 1
    list3 = [l1 if l1 != "A" for l1 in list1]
                               ^
SyntaxError: invalid syntax

逆にif 〜 elseの場合、後ろに書いてしまうとエラーが出ます。

list1 = ["A", "B", "C", "D", "E", "F", "G"]

list3 = [l1 for l1 in list1 if l1 != "A" else "G"]

print(list3)

実行結果
  File "<ipython-input-44-f59ce25d99fe>", line 1
    list3 = [l1 for l1 in list1 if l1 != "A" else "G"]
                                                ^
SyntaxError: invalid syntax

残念ながらelifで複数の条件分岐をさせるということはできないようです。

list1 = ["A", "B", "C", "D", "E", "F", "G"]

list3 = [l1 if l1 != "A" "G" elif l1 = "B" for l1 in list1]

print(list3)

実行結果
  File "<ipython-input-47-cbb37974b4ed>", line 1
    list3 = [l1 if l1 != "A" "G" elif l1 = "B" for l1 in list1]
                                    ^
SyntaxError: invalid syntax

ちなみにif 〜 elseを使って、リスト内包表記を使わない場合はこんな感じになります。

list1 = ["A", "B", "C", "D", "E", "F", "G"]

list3 = []

for l1 in list1:
    if l1 != "A":
        list3.append(l1)
    else:
        list3.append("G")
        
print(list3)

実行結果
['G', 'B', 'C', 'D', 'E', 'F', 'G']

やっぱり長くなってしまいます。

個人的になかなか覚えにくくて使っていなかったのですが、こうやってまとめてみるとプログラムがスッキリとして、結構効率が良さそうです。

ちなみに普段使うのは、上のように他のリストから新しいリストを作るという場面ではなく、例えば数値から新たにリストを作るといった場面で使いそうです。

list4 = [i for i in range(len(list1)) if i > 3]

print(list4)

実行結果
[4, 5, 6]

個人的な意見としては、自分がやりやすい方法でプログラミングしていけばいいと思っています。

無理にenumerate関数やリスト内包表記を使わなくても同じ処理をするプログラムを書くことは十分に可能ですし、それが分かりやすいという私みたいな人もいることでしょう。

ただこういうやり方もあるということを知っておくだけで選択肢が増えるので、頭の片隅に入れつつ、時々思い出すために使ってみるというのもいいことなんじゃないかなと思います。

ではでは今回はこんな感じで。

よかったらシェアしてね!
  • URLをコピーしました!

コメント

コメントする

目次