イテレータを二重ループで使うときは注意する
2021-12-17 説明が不足していたのと、間違ったことを書いていたので修正した
---
イテレータを生成する場所はfor .. inの後ろが安全 イテレータの性質を理解する
❌forの外であらかじめイテレータを生成すると、二重ループの場合に以下のようなことが起きる
code:py
...: b = iter(list('abc'))
...: for i in a:
...: for s in b:
...: print(i, s)
...:
1 a
1 b
1 c
外側のループの2周目の最初に、イテレータbは既に最後まで到達している
外側のループごとに、イテレータbを作り直す必要がある
✅内側のfor文が実行されるたびに、内側のイテレータを生成する
code:py
...: for i in a:
...: for s in iter(list('abc')):
...: print(i, s)
...:
1 a
1 b
1 c
2 a
2 b
2 c
3 a
3 b
3 c
❌期待した結果を得られない例
code:py
In : a = itertools.product('0', '1', repeat=2) ...: b = itertools.product('-', repeat=2)
...: for x in a:
...: for y in b:
...: print(x, y)
...:
('0', '0') ('+', '+')
('0', '0') ('+', '-')
('0', '0') ('-', '+')
('0', '0') ('-', '-')
✅for .. inの後ろでイテレータを生成する例
code:py
In : for x in itertools.product('0', '1', repeat=2): ...: for y in itertools.product('-', repeat=2):
...: print(x, y)
...:
...:
('0', '0') ('+', '+')
('0', '0') ('+', '-')
('0', '0') ('-', '+')
('0', '0') ('-', '-')
('0', '1') ('+', '+')
('0', '1') ('+', '-')
('0', '1') ('-', '+')
('0', '1') ('-', '-')
('1', '0') ('+', '+')
('1', '0') ('+', '-')
('1', '0') ('-', '+')
('1', '0') ('-', '-')
('1', '1') ('+', '+')
('1', '1') ('+', '-')
('1', '1') ('-', '+')
('1', '1') ('-', '-')
✅list化しておけばあらかじめ定義はできる。どちらのほうがコストが低いだろうか。
code:py
In : a = itertools.product('0', '1', repeat=2) ...: b = list(itertools.product('-', repeat=2))
...: for x in a:
...: for y in b:
...: print(x, y)
...:
('0', '0') ('+', '+')
('0', '0') ('+', '-')
('0', '0') ('-', '+')
('0', '0') ('-', '-')
('0', '1') ('+', '+')
('0', '1') ('+', '-')
('0', '1') ('-', '+')
('0', '1') ('-', '-')
('1', '0') ('+', '+')
('1', '0') ('+', '-')
('1', '0') ('-', '+')
('1', '0') ('-', '-')
('1', '1') ('+', '+')
('1', '1') ('+', '-')
('1', '1') ('-', '+')
('1', '1') ('-', '-')