この質問では、 @ lazyrは、ここizip_longest
からのイテレータの次のコードがどのように機能するかを尋ねます。
def izip_longest_from_docs(*args, **kwds):
# izip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D-
fillvalue = kwds.get('fillvalue')
def sentinel(counter = ([fillvalue]*(len(args)-1)).pop):
yield counter() # yields the fillvalue, or raises IndexError
fillers = repeat(fillvalue)
iters = [chain(it, sentinel(), fillers) for it in args]
try:
for tup in izip(*iters):
yield tup
except IndexError:
pass
それがどのように機能するかを理解しようとしていたとき、 「パラメーターとしてIndexError
送信されるイテレーターの1つで発生した場合はどうなるか」という質問に遭遇しました。izip_longest
それから私はいくつかのテストコードを書きました:
from itertools import izip_longest, repeat, chain, izip
def izip_longest_from_docs(*args, **kwds):
# The code is exactly the same as shown above
....
def gen1():
for i in range(5):
yield i
def gen2():
for i in range(10):
if i==8:
raise IndexError #simulation IndexError raised inside the iterator
yield i
for i in izip_longest_from_docs(gen1(),gen2(), fillvalue = '-'):
print('{i[0]} {i[1]}'.format(**locals()))
print('\n')
for i in izip_longest(gen1(),gen2(), fillvalue = '-'):
print('{i[0]} {i[1]}'.format(**locals()))
itertools
そして、モジュール内の機能とizip_longest_from_docs
動作が異なることが判明しました。
上記のコードの出力:
>>>
0 0
1 1
2 2
3 3
4 4
- 5
- 6
- 7
0 0
1 1
2 2
3 3
4 4
- 5
- 6
- 7
Traceback (most recent call last):
File "C:/..., line 31, in <module>
for i in izip_longest(gen1(),gen2(), fillvalue = '-'):
File "C:/... test_IndexError_inside iterator.py", line 23, in gen2
raise IndexError
IndexError
izip_longes
したがって、 fromのコードは例外をitertools
伝播しましたがIndexError
(私が思うに)、反復を停止するためのシグナルとして例外をizip_longes_from_docs
「飲み込んだ」ことがはっきりとわかります。IndexError
sentinel
私の質問は、モジュールIndexError
内のコードでの伝播をどのように回避したかということです。itertools