2017-10-14 6 views
1

次の質問に対するJeanの回答に続いて、Python converting strings in a list to numbersの場合、最小限のコードを実行するとStopIteration例外が発生します。ジェネレータとリストを含むPython StopIteration

primesおよびz2は空です。

私はトレースバックで回線の周りにループが必要かもしれないと思うが、私はどのように治療するのか分からないのですか?

トレースバック:CSVファイル内の

File "factorise_v32.py", line 118, in factorise 
    primes=[next(z2) for _ in xrange(b)] 
StopIteration 

サンプルデータ:

("2","3","5","7","11") 

最小限のコード:

import csv 

def factorise(N) 
    .... 
    z1=(int(x) for row in csv.reader(csvfile) for x in row) 
    .... 
    b=4 #b can be any positive integer 
    z2=(int(x) for row in csv.reader(csvfile) for x in row) 
    primes=[next(z2) for _ in xrange(b)] 
+1

'next()'は、 'z2'が使い尽くされたので例外を送出します。 'z2'には' b'要素はありません。 –

+0

@MartijnPieters理解を終了するために 'StopIteration'は扱われませんか? – schwobaseggl

+1

'z2'を直接*反復しないのはなぜですか?それをリストの理解にしたり、限られた数の要素を取得したい場合は 'slice()'を使います。 –

答えて

2

リストの内包が発電機ではないか自体をイテレータ。式側でStopIterationの例外が発生した場合でも停止しません。 iterablefor ... in <iterable>ループオーバーは、反復が行われたループforと通信するためにStopIterationを使用できますが、残りの構造体には及んでいません。

あなたはイテレータから要素のほとんどb数でを取得する必要がある場合は、itertools.islice()使用:

primes = list(islice(z2, b)) 

それが足りない場合は繰り返し処理時にbの要素を取る、以下のよz2の要素。

あなたはパッドアウトnext()デフォルト値を与えることで、より少ないb要素があった場合には0値の結果にしようとしたにリンクされているポストの以前のリビジョン。私はこれを達成するためにitertools.repeat()itertools.chain()を使用していると思います:z2が使い果たされた後

primes = list(islice(chain(z2, repeat(0)), b)) 

chain(z2, repeat(0))部分が延々と0値を追加します。 islice()は、そのシーケンスから要素をbと取ります。

デモ:あなたはない最初のファイルオブジェクトの巻き戻しをせずに、行に二回CSVファイルから読み込むことができません

>>> from itertools import chain, repeat, islice 
>>> z2 = iter([1, 2, 3]) 
>>> list(islice(z2, 5)) # up to 5 
[1, 2, 3] 
>>> z2 = iter([1, 2, 3]) # pad with zeros 
>>> list(islice(chain(z2, repeat(0)), 5)) 
[1, 2, 3, 0, 0] 

注意。あなたのコードは2つの場所でcsv.reader(csvfile)を使用していますが、csvfileファイルオブジェクトは最初に戻りません。再度読み取る前にcsvfile.seek(0)を追加してください。

+0

@ Jean-FrançoisFabre:言い回しが調整されました。 –

+0

いつものように完璧:最近私はあなた自身の上で "私はパイロット"ではありませんでしたか? –

+1

@Jean ssssh!彼のプログラミングは、彼が実際にそれを見つけたら壊れるかもしれません! :p –

関連する問題