2016-12-08 6 views
0

何が起きているのかをより深く理解するために、プログラミングには触れません。IndexError:リストのインデックスが範囲外ですが、リストの長さはOKです

ゴール:ファイルを開き、最初の10行を印刷します。 (頭のようなコマンド)

コード:結果

with open('file') as f: 
     for i in range(0,10): 
      print([line.strip('\n') for line in f][i]) 

プリント最初の行の罰金は、範囲外エラーにを返し

ファイル:20との単純なテキストファイルです行ごとに50文字以下

FYI - 削除された範囲行とタイプ(リスト)と長さ(20)の両方が表示されます。問題異なるコードで望ましい結果を得ることができ(行に1>でない限り)

ことなく、特定のインデックスを印刷していますが、実際にファイルを反復処理することができます

+0

お試しください:open( 'file')としてf: for f.readlines()内の行: – eyllanesc

+0

@eyllanescまたは 'for line in f' –

答えて

3

として/を使用して改善しようとしています。あなたはここで何をすべきですか。あなたのコードが失敗している

with open('file') as f: 
    for i, line in enumerate(file, start=1): 
     # Get out of the loop if we hit 10 lines 
     if i >= 10: 
      break 
     # Line already has a '\n' at the end 
     print(line, end='') 

理由は、あなたのリストの内包表記は次のとおりです。

[line.strip('\n') for line in f] 

初めて、ファイル内の行のすべてを消費し、あなたのループを通って。今度はあなたのファイルには行がないので、次回はファイル内のすべての行のリストを作成し、[1] st要素を取得しようとします。しかし、ファイルの最後には行がないので、それは存在しません。

あなたは

lines = [line.rstrip('\n') for line in f] 
for i in range(10): 
    print(lines[i]) 

を行う可能性があるとして、しかし、あなたはちょうど

lines = f.readlines() 

を行う可能性があるため、それは、また、愚かだしかし、それはまた愚かだ主に、あなたのコードを維持したい場合であればあなたがこれを行うことができるので、あなたはこれを行うことができるので、10行目までにします:

with open('file') as f: 
    print('\n'.join(f.readlines()[:10])) 

いくつかの更なる説明:あなたのコードを修正することができ

最短と最悪方法は、コードを1行追加することである:

with open('file') as f: 
     for i in range(0,10): 
      f.seek(0) # Add this line 
      print([line.strip('\n') for line in f][i]) 

を今すぐあなたのコードは動作します - しかし、これはです恐ろしいあなたのコードを動作させる方法。 理由は、コードが最初に期待したとおりに動作しないということは、ファイルが消耗品のイテレータであることです。それは、あなたが読んだときに、最終的に読むことがなくなることを意味します。あなたはそれが何も出力しないことがわかります

print(file.read()) 

:ここでは簡単な例です:あなたはファイルから読み取るしようとした場合

import io 

file = io.StringIO(''' 
This is is a file 
It has some lines 
okay, only three. 
'''.strip()) 

for line in file: 
    print(file.tell(), repr(line)) 

これは今

18 'This is is a file\n' 
36 'It has some lines\n' 
53 'okay, only three.' 

を出力します。これは、ファイルを "消費した"ためです。私は明らかにまだディスク上にありますが、イテレータはファイルの最後に達しています。しかし、示されているように、あなたはファイルを探すことができます。

print(file.tell()) 
file.seek(0) 
print(file.tell()) 
print(file.read()) 

ファイル全体が表示されます。しかし、他のポジションはどうですか?私たちは、ファイルから読み込むときに

file.seek(36) 
print(file.read(4)) # => okay 
print(file.tell()) # => 40 

するか、私たちは、イテレータを消費しての最後に取得することを反復処理:サイドノートとして

file.seek(36) 
print(file.read()) # => okay, only three. 

、あなたも読むことをどのくらい指定することができますファイル。新しいツールを使用して元のコードに戻り、何が起きているのかを探そう。

with open('file') as f: 
    print(f.tell()) 
    lines = [line.rstrip('\n') for line in f] 
    print(f.tell()) 
    print(len([line for line in f])) 
    print(lines) 

ファイル内の別の場所にいることがわかります。そして、2番目のリストの理解は空のリストを生成します。これは、リストの理解度が評価されると直ちに実行されるからです。あなたがこれを行うときに:あなたが最初の時間をやって何

for i in range(10): 
    print([line.strip('\n') for line in f][i]) 

i = 0をして、リストの内包は、ファイルの最後まで読み込みます。これで、リストの最初の要素、つまりファイルの最初の行が[0]番目の要素になります。しかし、ファイルイテレータはファイルの最後にあります。

これでリストの先頭に戻り、i = 1に戻ります。今度はファイルの最後まで繰り返しますが、すでに終わっているため、読み込む行はありません。[][0]の要素を取得しようとしています。しかし、そこには何もありません。だから我々はIndexErrorを得る。

リストコンパイル便利ですが、開始時にはforループを作成してリストの理解に変換する方がはるかに簡単です。

with open('file') as f: 
    for i, line in enumerate(file, start=10): 
     if i < 10: 
      print(line.rstrip()) 

今、私たちはリスト内包の内側に印刷するべきではありませんので、代わりに私たちはすべてのものを収集します:だからあなたは、このような何かを書くかもしれません。私たちは、私たちが望むものを入れてから始める:

[line.rstrip() for i, line in enumerate(f) 

そして最後に、フィルタおよび当社の閉じ括弧を追加します:

[line.rstrip() 

は今少しのための追加リストの詳細については

[line.rstrip() for i, line in enumerate(f) if i < 10] 

をこれは素晴らしいリソースです:http://treyhunner.com/2015/12/python-list-comprehensions-now-in-color/

+0

ありがとう、ウェイン。私の 'の前にコードを使用する'はまだ私は周りに私の頭をラップしようとしている何かです。 –

+0

これで問題が解決した場合は、左側にチェックマークを付けることで受け入れ可能となります。それが特に有用な場合は、それをアップヴォートすることもできます。あなたが「私の 'for 'の前にコードを使用する」と言うとき、あなたはリストの理解を意味しますか(例えば、' 'データの中のもの'')、 'のために' for'を別のブロックの中に入れ子にすることを意味しますか? (...)としてf:行のためにf:print(行) '? –

+0

***ああ、私は 'for'ステートメントの前に 'line.strip'を使用すると、実際には 'line.strip'をファイルのすべての行に適用し、その結果を行のリストに出力します。そして、それをもう一度繰り返すと、ファイル内のすべての行が既に処理されていることが分かります。したがって、空のリストを出力するだけなので、エラーは発生しません。これを説明する時間をとってくれてありがとう。 :) –

関連する問題