Pythonの反復処理いろいろ

# はじめに
Pythonの反復処理関連の関数、ライブラリについてまとめる。
関数/ライブラリ|内容
---|---
[range](#range)|反復処理の範囲を指定する。
[reversed](#reversed)|逆順で反復処理する。
[enumerate](#enumerate)|反復処理のインデックスを付ける。
[zip](#zip)|複数の配列や辞書をまとめて反復処理する。
[generator/yield](#generatoryield)|順次、値を返答する処理関数。
[tqdm](#tqdm)|反復処理の進捗状況を表示するライブラリ。
[itertools](#itertools)|反復処理の強化ライブラリ。


## range
反復処理の範囲を指定して使う。```range(stop)```で終わりを指定して使うか、```range(start,stop)```で開始と終わりを指定して使うことができる。```range(start,stop,step)```としてあげればステップも指定可能。
```python:range_test.py
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
逆順で反復処理する。
```python:reversed_test.py
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
反復処理のインデックスを付ける。インデックスの開始位置も指定できる。

```python:enumerate_test.py
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とセットで使うことも可能。
```python:zip.py
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```の反復処理で値を取り出す。いまいち用途が思い浮かばずいい例が書けなかった。。

```python:generator_yield_test.py
#--------------------------
# 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=```で反復処理のサイズを指定してあげればプログレスバーが表示される。

```python:tqdm_test.py
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
こういう反復処理したいんだけどな、という処理を実現できる、かゆいところに手の届くライブラリ。色々あるが、自分がよく使うだろうなという例を記載する。

公式サイトは下記

https://docs.python.org/ja/3/library/itertools.html#module-itertools


ツール|内容
---|---
itertools.zip_longest(  ,filevalue=<値>)|zip処理した時に、要素数が足りない方に任意の値を埋める。fillvalueに埋めたい値を設定。
itertools.islice(...,start,stop,step)|開始(start),終了(stop),ステップ(step)を指定して反復処理する。使用しないパラメータはNoneを設定する。zipとも組みあせて使用することができる。


```python:itertools_test.py
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'

```
[戻る](#はじめに)

-----
**参考にした記事、サイト**

https://qiita.com/SeeLog/items/73c054a37722890b17a2