はじめに
Pythonの反復処理関連の関数、ライブラリについてまとめる。
関数/ライブラリ | 内容 |
---|---|
range | 反復処理の範囲を指定する。 |
reversed | 逆順で反復処理する。 |
enumerate | 反復処理のインデックスを付ける。 |
zip | 複数の配列や辞書をまとめて反復処理する。 |
generator/yield | 順次、値を返答する処理関数。 |
tqdm | 反復処理の進捗状況を表示するライブラリ。 |
itertools | 反復処理の強化ライブラリ。 |
range
反復処理の範囲を指定して使う。range(stop)
で終わりを指定して使うか、range(start,stop)
で開始と終わりを指定して使うことができる。range(start,stop,step)
としてあげればステップも指定可能。
test_data=[]
#0→10 1ステップ
for i in range(10):
test_data.append(i)
print(f'# {type(test_data) = } / {len(test_data) = } / {test_data = }')
# type(test_data) = <class 'list'> / len(test_data) = 10 / test_data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
test_data.clear()
#2→10 1ステップ
for i in range(2,10):
test_data.append(i)
print(f'# {type(test_data) = } / {len(test_data) = } / {test_data = }')
# type(test_data) = <class 'list'> / len(test_data) = 8 / test_data = [2, 3, 4, 5, 6, 7, 8, 9]
test_data.clear()
#2→10 2ステップ
for i in range(2,10,2):
test_data.append(i)
print(f'# {type(test_data) = } / {len(test_data) = } / {test_data = }')
# type(test_data) = <class 'list'> / len(test_data) = 4 / test_data = [2, 4, 6, 8]
test_data.clear()
#10→0 -1ステップ
for i in range(10,0,-1):
test_data.append(i)
print(f'# {type(test_data) = } / {len(test_data) = } / {test_data = }')
# type(test_data) = <class 'list'> / len(test_data) = 10 / test_data = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
reversed
逆順で反復処理する。
test_data=['A','B','C','D','E','F','G','H','I','J']
for d in reversed(test_data):
print(f'# {d = }')
# d = 'J'
# d = 'I'
# d = 'H'
# d = 'G'
# d = 'F'
# d = 'E'
# d = 'D'
# d = 'C'
# d = 'B'
# d = 'A'
enumerate
反復処理のインデックスを付ける。インデックスの開始位置も指定できる。
test_data=['A','B','C','D','E','F','G','H','I','J']
#0~
for i,d in enumerate(test_data):
print(f'# {i = } / {d = }')
# i = 0 / d = 'A'
# i = 1 / d = 'B'
# i = 2 / d = 'C'
# i = 3 / d = 'D'
# i = 4 / d = 'E'
# i = 5 / d = 'F'
# i = 6 / d = 'G'
# i = 7 / d = 'H'
# i = 8 / d = 'I'
# i = 9 / d = 'J'
#2~
for i,d in enumerate(test_data,2):
print(f'# {i = } / {d = }')
# i = 2 / d = 'A'
# i = 3 / d = 'B'
# i = 4 / d = 'C'
# i = 5 / d = 'D'
# i = 6 / d = 'E'
# i = 7 / d = 'F'
# i = 8 / d = 'G'
# i = 9 / d = 'H'
# i = 10 / d = 'I'
# i = 11 / d = 'J'
zip
複数の配列や辞書をまとめて反復処理する。複数を一つにまとめて、tuple化することもできる。enumerateとセットで使うことも可能。
test_data=['a','b','c','d','e','f','g','h','i','j']
test_data2=['A','B','C','D','E','F','G','H','I','J']
for d1,d2 in zip(test_data, test_data2):
print(f'# {d1 = } / {d2 = }')
# d1 = 'a' / d2 = 'A'
# d1 = 'b' / d2 = 'B'
# d1 = 'c' / d2 = 'C'
# d1 = 'd' / d2 = 'D'
# d1 = 'e' / d2 = 'E'
# d1 = 'f' / d2 = 'F'
# d1 = 'g' / d2 = 'G'
# d1 = 'h' / d2 = 'H'
# d1 = 'i' / d2 = 'I'
# d1 = 'j' / d2 = 'J'
for d in zip(test_data, test_data2):
print(f'# {type(d) = } / {d = }')
# type(d) = <class 'tuple'> / d = ('a', 'A')
# type(d) = <class 'tuple'> / d = ('b', 'B')
# type(d) = <class 'tuple'> / d = ('c', 'C')
# type(d) = <class 'tuple'> / d = ('d', 'D')
# type(d) = <class 'tuple'> / d = ('e', 'E')
# type(d) = <class 'tuple'> / d = ('f', 'F')
# type(d) = <class 'tuple'> / d = ('g', 'G')
# type(d) = <class 'tuple'> / d = ('h', 'H')
# type(d) = <class 'tuple'> / d = ('i', 'I')
# type(d) = <class 'tuple'> / d = ('j', 'J')
for i,(d1,d2) in enumerate(zip(test_data, test_data2)):
print(f'# {i = } / {d1 = } / {d2 = }')
# i = 0 / d1 = 'a' / d2 = 'A'
# i = 1 / d1 = 'b' / d2 = 'B'
# i = 2 / d1 = 'c' / d2 = 'C'
# i = 3 / d1 = 'd' / d2 = 'D'
# i = 4 / d1 = 'e' / d2 = 'E'
# i = 5 / d1 = 'f' / d2 = 'F'
# i = 6 / d1 = 'g' / d2 = 'G'
# i = 7 / d1 = 'h' / d2 = 'H'
# i = 8 / d1 = 'i' / d2 = 'I'
# i = 9 / d1 = 'j' / d2 = 'J'
for i,d in enumerate(zip(test_data, test_data2)):
print(f'# {i = } / {type(d) = } / {d = }')
# i = 0 / type(d) = <class 'tuple'> / d = ('a', 'A')
# i = 1 / type(d) = <class 'tuple'> / d = ('b', 'B')
# i = 2 / type(d) = <class 'tuple'> / d = ('c', 'C')
# i = 3 / type(d) = <class 'tuple'> / d = ('d', 'D')
# i = 4 / type(d) = <class 'tuple'> / d = ('e', 'E')
# i = 5 / type(d) = <class 'tuple'> / d = ('f', 'F')
# i = 6 / type(d) = <class 'tuple'> / d = ('g', 'G')
# i = 7 / type(d) = <class 'tuple'> / d = ('h', 'H')
# i = 8 / type(d) = <class 'tuple'> / d = ('i', 'I')
# i = 9 / type(d) = <class 'tuple'> / d = ('j', 'J')
generator/yield
yieldは、関数のreturnの代わりとなるもので、関数内の処理を一時中断、返答する機能。generatorは、yieldを使った関数のことをいう。generator内の変数はyieldで中断した時の値を保持できる。generatorの戻り値は、generator型なので=
で取り出しても、そのまま値として処理できない。list()
でリスト化するか、for
の反復処理で値を取り出す。いまいち用途が思い浮かばずいい例が書けなかった。。
#--------------------------
# yieldを使ったgenerator関数
#--------------------------
def generator_func():
for i in range(10):
yield i
print(f'# {type(generator_func()) = }\n# {generator_func() = }')
# type(generator_func()) = <class 'generator'>
# generator_func() = <generator object generator_func at 0x00000207D6EBA900>
# list()でリスト化
print(f'# {list(generator_func()) = }')
# list(generator_func()) = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# for で値取り出し
for i in generator_func():
print(f'# {i=}')
# i=0
# i=1
# i=2
# ~
# i=8
# i=9
tqdm
進捗状況をプログレスバーで表示する。長ーい処理がいつ終わるのか?を目視で確認できるので、重宝するライブラリ。下記は例なので長くない処理。zipやenumerateでtqdmを使うと、プログレスバーが出なくなる。その場合はtotal=
で反復処理のサイズを指定してあげればプログレスバーが表示される。
from tqdm import tqdm
#基本----------------------------------------------
test_data=['a','b','c','d','e','f','g','h','i','j']
for i in tqdm(test_data):
pass
# 100%|██████████████████████████████████████████████████████████████████████████████████████| 1000/1000 [00:00<?, ?it/s]
#zipやenumerateと一緒にtqdm使う 1-------------------
test_data=['a','b','c','d','e','f','g','h','i','j']
test_data2=['A','B','C','D','E','F','G','H','I','J']
for i,(d1,d2) in tqdm( enumerate(zip(test_data, test_data2)) ):
pass
#10it [00:00, ?it/s]
#zipやenumerateと一緒にtqdm使う 2-------------------
for i,(d1,d2) in tqdm( enumerate(zip(test_data, test_data2)) , total=len(test_data)):
pass
# 100%|██████████████████████████████████████████████████████████████████████████████████████| 1000/1000 [00:00<?, ?it/s]
itertools
こういう反復処理したいんだけどな、という処理を実現できる、かゆいところに手の届くライブラリ。色々あるが、自分がよく使うだろうなという例を記載する。
公式サイトは下記
ツール | 内容 |
---|---|
itertools.zip_longest( ,filevalue=<値>) | zip処理した時に、要素数が足りない方に任意の値を埋める。fillvalueに埋めたい値を設定。 |
itertools.islice(...,start,stop,step) | 開始(start),終了(stop),ステップ(step)を指定して反復処理する。使用しないパラメータはNoneを設定する。zipとも組みあせて使用することができる。 |
import itertools
# itertools.zip_longest()
test_data=['a','b','c','d']
test_data2=['A','B','C','D','E','F','G','H','I','J']
for d1, d2 in itertools.zip_longest(test_data, test_data2, fillvalue='-'):
print(f'# {d1 = } / {d2 = }')
# d1 = 'a' / d2 = 'A'
# d1 = 'b' / d2 = 'B'
# d1 = 'c' / d2 = 'C'
# d1 = 'd' / d2 = 'D'
# d1 = '-' / d2 = 'E'
# d1 = '-' / d2 = 'F'
# d1 = '-' / d2 = 'G'
# d1 = '-' / d2 = 'H'
# d1 = '-' / d2 = 'I'
# d1 = '-' / d2 = 'J'
# itertools.islice()
test_data=['0','1','2','3','4','5','6','7','8','9']
test_data2=['A','B','C','D','E','F','G','H','I','J']
# start=0, stop =5
for d1, d2 in itertools.islice( zip(test_data, test_data2) , None,5):
print(f'# {d1 = } / {d2 = }')
# d1 = '0' / d2 = 'A'
# d1 = '1' / d2 = 'B'
# d1 = '2' / d2 = 'C'
# d1 = '3' / d2 = 'D'
# d1 = '4' / d2 = 'E'
# start=2, stop =5
for d1, d2 in itertools.islice( zip(test_data, test_data2) , 2, 5):
print(f'# {d1 = } / {d2 = }')
# d1 = '2' / d2 = 'C'
# d1 = '3' / d2 = 'D'
# d1 = '4' / d2 = 'E'
# start=2, stop =end
for d1, d2 in itertools.islice( zip(test_data, test_data2) , 2, None):
print(f'# {d1 = } / {d2 = }')
# d1 = '2' / d2 = 'C'
# d1 = '3' / d2 = 'D'
# d1 = '4' / d2 = 'E'
# d1 = '5' / d2 = 'F'
# d1 = '6' / d2 = 'G'
# d1 = '7' / d2 = 'H'
# d1 = '8' / d2 = 'I'
# d1 = '9' / d2 = 'J'
# start=0, stop =end, step=2
for d1, d2 in itertools.islice( zip(test_data, test_data2) , None, None, 2):
print(f'# {d1 = } / {d2 = }')
# d1 = '0' / d2 = 'A'
# d1 = '2' / d2 = 'C'
# d1 = '4' / d2 = 'E'
# d1 = '6' / d2 = 'G'
# d1 = '8' / d2 = 'I'
参考にした記事、サイト