0

次のようなリスト形式のコンテンツを含む txt ファイルがあります。

[1,2,3,4]
[5,6,7,8]

次のコードを使用して、これらのリストをリストに入れました。

t = open('filename.txt', 'r+w')
contents = t.readlines()

alist = []

for i in contents:
    alist.append(i)

私が走るとき

alist[0]

私は得る

[1,2,3,4]

しかし、私が走るとき

for a in alist:
    print a[0]

私は得る

[

リストの最初の値の代わりに。

4

3 に答える 3

4

.readlines()行を文字列として読み取ります。その文字列の最初の文字は[.

テキスト ファイルを読み取ってデータ構造に「逆シリアル化」する場合、最も簡単な方法は Python の組み込みeval()関数を使用することです。より安全な方法は、 を使用することast.literal_eval()です。

http://docs.python.org/2/library/ast.html?highlight=literal#ast.literal_eval

推奨コード:

import ast

with open("filename.txt") as f:
    alist = [ast.literal_eval(line) for line in f]

print(type(alist[0]))  # prints: <type 'list'>
print(alist[0]) # prints: [1,2,3,4]

を呼び出したいと思うことはほとんどありません.readlines()。ファイルのすべての行を丸呑みするため、ファイルが非常に大きい場合、プログラムのメモリ使用量が大幅に増加します。開いているファイル ハンドル オブジェクト (私の例ではf) は反復子として使用でき、反復されるたびにファイルから 1 行が生成されます。そのため、forループまたはリスト内包表記は、ファイルから一度に 1 行ずつ取り出します。したがって、このサンプル プログラムはファイル全体をメモリに保持しません。リストを作成する間、一度に 1 行だけ保持します。このプログラムが呼び出された場合.readlines()、すべての行とリストが保持されるため、ピーク時のメモリ使用量が高くなります。(もちろん、この例のような小さな入力ファイルでは問題ありません。しかし、メモリ効率の良い方法で物事を行うのは簡単です。なぜですか?)

withファイルを開くために使用することは、常に良い習慣です。そうすれば、ファイルの処理が完了すると、ファイルが適切に閉じられることがわかります。

リスト内包表記を使用して の結果のリストを作成します。ast.literal_eval()これは、指定された入力ファイルに対して行ごとにリストを返すためalist、リストのリストになります。

于 2013-03-05T20:50:52.080 に答える
3

これらのファイルを継承またはダウンロードしたばかりで、フォーマットについて何もできず、それらが Pythonlistの行として扱われることになっていることがわかっている場合ast.literal_evalは、steveha が説明したように、これが最良の答えです。

t = open('filename.txt', 'r')
alist = []    
for i in contents:
    alist.append(ast.literal_eval(i))

これらのファイルを継承またはダウンロードし、形式を推測しているだけの場合、実際には JSON の行として読み取られることを意図している可能性があります。これは、有効な Python リテラルであるのと同様に、それらが間違いなく有効な JSON であるためです。その場合:

t = open('filename.txt', 'r')
alist = []    
for i in contents:
    alist.append(json.loads(i))

ただし、これらのファイルを最初に作成したのが自分である場合は、シリアル化用に設計された方法でファイルを作成する必要があります。

たとえば、これの代わりに:

t = open('filename.txt', 'w')
for i in alist:
    print >>t, i

次のようにします。

t = open('filename.txt', 'w')
json.dump(alist, t)

次に、読み取りコードを次のように記述できます。

t = open('filename.txt', 'r')
alist = json.load(t)

JSON、YAML、または Pickle などのシリアル化形式の要点は、値を書き込んで後で同じ値を読み戻せるように特別に設計されていることです。

、 などのprint関数はそのために設計されていません。後で読み返すことが困難または不可能な場合でも、人間が読める形式で値を表示できるように設計されています。str

関数reprはその中間にあります。これは、対話型プロンプトで遊んでいる人間が読めるように設計されているため、可能であれば、プロンプトに入力して同じ値を取得できる文字列を提供します。これは、が の逆であるのと同様に、 がのast.literal_eval逆である場合があることを意味します。ただし、これが機能する型を扱う場合でも、これに依存するべきではありません。reprjson.loadjson.dump


コードに関するいくつかの補足事項:

t = open('filename.txt', 'r+w')

ファイルを読み取るだけの場合は、書き込み用にファイルを開こうとしないでください。また、読み取りと書き込みの両方で開きたい場合、正しいモード文字列はではr+なくr+wです。(あなたが行った方法は技術的にはエラーですが、ほとんどのバージョンの Python は を無視するwので、問題はありません。)

モードがrの場合は、それがデフォルトであるため、指定する必要はまったくありません。

その間、あなたは決してcloseファイルを持っていません。これを行う最も簡単な方法は、withステートメントを使用することです。

contents = t.readlines()

電話する正当な理由はほとんどありませんreadlines()。これにより一連の行が得られますが、ファイル自体はすでに一連の行です。あなたがしているのは、それの追加のコピーを作成することだけです。

alist = []

for i in contents:
    alist.append(i)

このパターン (空のリストを作成し、ループ内でそれに追加する) は非常に一般的であるため、Python にはリスト内包表記と呼ばれるショートカットがあります。内包表記は、明示的なループよりも冗長でなく、読みやすく、間違えにくく、高速であるため、ほとんどの場合に使用する価値があります。

最後に、変数に意味のある名前を付けることをお勧めします。特に、他の誰か (または 6 か月後の自分自身) にコードをデバッグしてもらいたい場合。変数が完全に機能している場合は、変数が何を意味するかを知ることができますが、そうでない場合は、変数が何を意味するのかを推測できない限り、変数を修正することはできず、名前はそれを示す最良の方法です.

したがって、すべてをまとめると、元のコードは次のように記述できます。

with open('filename.txt') as textfile:
    alist = [line for line in textfile]

そして、さまざまな修正バージョンは次のとおりです。

with open('filename.txt') as textfile:
    alist = [ast.literal_eval(line) for line in textfile]

with open('filename.txt') as textfile:
    alist = [json.loads(line) for line in textfile]

with open('filename.txt') as textfile:
    alist = json.load(textfile)
于 2013-03-05T21:14:06.417 に答える
0

あなたが持っているのは、文字列のリストです。括弧とカンマを含む文字列は魔法のようにリストではなく、単に括弧とカンマを含む文字列です。

alistリストです。あなたのループでaは、そのリストの項目alist[0]ですalist[1]。したがって、は、 、 などa[0]を要求します。各行の最初の文字です。そして、それがあなたが得るものです。alist[0][0]alist[1][0]

それを実際の Python リストに変換する場合は、 を使用しますast.literal_eval()

于 2013-03-05T20:58:19.577 に答える