簡體   English   中英

文件中的.readlines()列表未索引值

[英].readlines() list in a file not indexing values

我有一個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]

我懂了

[

而不是列表中的拳頭值。

.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 )可以用作迭代器,並且每次對其進行迭代都會從文件中產生一行。 因此, for循環或列表理解將一次從文件中拉一行。 因此,此示例程序不會將整個文件保留在內存中; 在構建列表時,它一次只保留一行。 如果此程序調用.readlines() ,它將保留所有行以及列表,因此峰值內存使用率將更高。 (當然,對於本例中的這么小的輸入文件來說,這沒關系。但是,以內存高效的方式來做事情很容易,所以為什么不呢?)

with一起使用總是打開文件的好習慣。 然后,您知道完成該文件后將正確關閉該文件。

我們使用列表ast.literal_eval()來構建ast.literal_eval()結果的列表,該列表對於給定的輸入文件每行返回一個列表,因此alist將是列表的列表。

如果您只是繼承或下載了這些文件,並且對格式無能為力,並且知道將它們視為Python list s行,則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之類的序列化格式的全部要點是,它們是經過專門設計的,以便您可以寫入一個值,然后再讀回該相同的值。

諸如printstr等功能並非為此設計; 它們經過設計,因此即使以后很難或不可能讀回,您也可以以人類最易理解的形式顯示值。

函數repr在兩者之間。 它被設計為對使用交互式提示的人類可讀,因此,如果可能,它會為您提供一個字符串,您可以在該字符串中鍵入以獲取相同的值。 這意味着,在某些情況下, ast.literal_eval是逆repr ,就像json.load是逆json.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都有一個捷徑,稱為列表理解。 與顯式循環相比,理解不那么冗長,更易讀,更容易出錯,並且速度更快,因此值得在大多數時間使用它們。

最后,最好給變量賦予有意義的名稱。 特別是如果您希望其他人(或您自己,六個月后)能夠調試您的代碼。 如果它的正常使用,我們可以告訴變量由他們究竟意味着什么做的,但如果沒有的話,我們不能修復它,除非我們可以猜測他們應該意味着什么,和名字對信號的最佳途徑。

因此,將所有內容放在一起,原始代碼可以寫為:

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)

您所擁有的是字符串列表。 帶有方括號和逗號的字符串不是神奇的列表,它只是帶有方括號和逗號的字符串。

alist是列表。 在循環中, a是該列表中的一項:首先是alist[0] ,然后是alist[1] ,依此類推。 因此, a[0]要求alist[0][0]alist[1][0]等:每行的第一個字符。 這就是您得到的。

如果要將其轉換為實際的Python列表,請使用ast.literal_eval()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM