[英].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之類的序列化格式的全部要點是,它們是經過專門設計的,以便您可以寫入一個值,然后再讀回該相同的值。
諸如print
, str
等功能並非為此而設計; 它們經過設計,因此即使以后很難或不可能讀回,您也可以以人類最易理解的形式顯示值。
函數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.