2013-08-20 5 views
1

Я пытаюсь сделать некоторые манипуляции с текстом в Python и сталкиваюсь с множеством проблем, главным образом из-за фундаментального непонимания того, как работает манипуляция с файлами на Python, поэтому я надеюсь это прояснить.Понимание итерации файлов в Python

Так позволяет сказать, что я итерацию через текстовый файл с именем «my.txt» и имеет следующее содержание:

3 10 7 8  
2 9 8 3 
4 1 4 2 

код я использую перебирать файл:

file = open ("my.txt", 'r') 
for line in file: 
    print line` 

Я скопировал и вставил вышеуказанный код из учебника. Я знаю, что он делает, но я не знаю, почему это работает, и это меня беспокоит. Я пытаюсь понять, что представляет собой переменная «строка» в файле. Это тип данных (строка?) Или что-то еще. Мой инстинкт подсказывает мне, что каждая строка представляет собой строку, которую можно было бы манипулировать (это то, что я хочу), но я также понимаю, что строки неизменяемы в Python.

Какую роль играет память во всем этом, если мой файл слишком велик, чтобы вписаться в память, будет ли он работать? Будет ли строка [3] позволять мне получить доступ к четвертому элементу в каждой строке? Если я только хочу работать на второй линии я могу сделать:

if line == 2: 

внутри для цикла?

Возможно, стоит отметить, что я довольно новичок в Python и исхожу из фона C \ C++ (не используется для неизменяемых строк). Я знаю, что я втиснул несколько вопросов в один, но любое разъяснение по общей теме было бы действительно полезно :)

+3

Я считаю, что вы должны прочитать [Python Tutorial] (http://docs.python.org/2/tutorial/controlflow.html#for- заявления). 'line' - это, как вы думали, строка. В частности, это «строка», то есть на каждой итерационной строке «строка» присваивается целая строка в файле. Строки неизменны в python (как и на большинстве других языков), но они предоставляют множество методов для их управления (создания новых строк). Что касается памяти: итерация по файлу * не * чтение всего файла в память. Он считывается кусками (избегая как слишком большого потребления памяти, так и слишком низких характеристик). – Bakuriu

+0

Если вы хотите иметь как содержимое строки, так и номер строки, вы можете использовать 'enumerate':' для индекса, строка в enumerate (file_object) 'Это будет присвоить' index = 0' первой строке, а затем 'index = 1' и т. Д. (Синтаксис 'a, b, c, d, e в iterable' называется tuple-распаковкой, о котором стоит прочитать, поскольку он используется много). – Bakuriu

+0

Обратите внимание, что при работе с файлами в Python вы всегда должны использовать [инструкцию 'with'] (http://www.youtube.com/watch?v=lRaKmobSXF4). –

ответ

1

Предположим, у вас есть тот же файл:

3 10 7 8\n  
2 9 8 3\n 
4 1 4 2\n 

Есть много file methods, которые работают на file object

В Python, вы можете прочитать файл символ за символом, C стиль:

with open('/tmp/test.txt', 'r') as fin:  # fin is a 'file object' 
    while True: 
     ch=fin.read(1) 
     if not ch: 
      break 
     print ch,       # comma suppresses the CR 

Вы можете прочитать весь файл в виде одной строки:

with open('/tmp/test.txt', 'r') as fin: 
    data=fin.read() 
    print data  

В перечисленных линиях:

with open('/tmp/test.txt', 'r') as fin: 
    for i, line in enumerate(fin): 
     print i, line  

В списке строк:

with open('/tmp/test.txt', 'r') as fin: 
    data=fin.readlines() 

идиом цикла по файловому объекту:

for line in fin:     # 'fin' is a file object result of open 
    print line 

является синонимом:

for line in fin.readline(): 
    print line 

и похожий на:

for line in 'line 1\nline 2\nline 3'.splitlines(): 
    print line 

После того, как вы привыкнете к петлям стиля Python (или Perl, или Obj C или Java петля типа диапазона), что цикл по элементам чего-то - использовать их без много думая об этом.

Если вы хотите, чтобы индекс каждого элемента - используйте enumerate

1

В Python вы можете выполнять итерацию прямо над файлом. Лучший способ сделать это с with заявления, например:

with open("myfile.txt") as f: 
    for i in f: 
     # do stuff to each line in the file 

Линия представляет собой строка, представляющая каждую строку (разделенный символ новой строки) в файле. Если вы хотите работать на второй линии, вы могли бы сделать что-то вроде этого:

with open("myfile.txt") as f: 
    list_of_file = list(f) 
    second_line = list_of_file[2] 

Если затем вы хотите получить доступ к части второй линии, которую вы можете разделить его пробелами в другой список, как так:

second_number_in_second_line = second_line.split()[1] 

Что касается памяти, переборе файла непосредственно делает не читать все это в памяти, однако, превращая его в list делает. Если вы хотите получить доступ к отдельным линиям без этого, используйте itertools.islice.

+3

Это не отвечает на вопрос. – user2357112

+0

Что делать, если я только хотел что-то сделать для определенной строки/линий и получить доступ к определенным элементам в каждой строке. – user2202911

+0

См. Редактирование, я случайно отправил его слишком рано. – rlms

1

На каждой итерации переменная line заполняется содержимым последующих строк, считанных из файла. Таким образом, вы будете иметь:

"3 10 7 8" в первой итерации
"2 9 8 3" во второй итерации
т.д.

Чтобы получить номера по отдельности, используйте метод разделения: link.

Таким образом, сравнение line с 2 не вызывает чувства. Если вы хотите, чтобы определить номера строк, вы можете попробовать:

lineNumber = 0 
for line in file: 
    print line 
    if lineNumber == 2: 
    print "that was the second line!" 
    lineNumber += 1 

Как было предложено в комментариях, вы можете упростить это с помощью enumerate:

for lineNumber, line in enumerate(file): 
    print line 
    if lineNumber == 2: 
     print "that was the second line!" 
+3

лучше использовать 'enumerate' здесь. это сделано для вещей точно так, как это –

+0

@BartoszKP Итак, на второй итерации элементы «3 10 7 8» полностью исчезли, если я не храню их как переменную на первой итерации? Допустим, мне нужно делать манипуляции с файлами, в которых числа, которые я хочу разделить, зависят от чисел, которые были разделены на предыдущую итерацию. Это можно сделать? – user2202911

+0

@PhillipCloud Спасибо за подсказку! – BartoszKP

3

line является строкой текста, представляется в виде строка. Строки неизменяемы, но это не проблема для их манипулирования; all variables in Python are references, and assigning to a variable points the reference to a new object. (В C++ вы не можете изменить, где ориентировочные точки.) Итерация по файлу повторяется по строкам, поэтому на каждой итерации line ссылается на новую строку, представляющую следующую строку входного файла.

Если вы знакомы с range-based for loops или другими конструкциями для каждого из них, так работает for Python. Переменная цикла не является счетчиком; вы не можете сделать

if line == 2: 

потому line не индекс строки; это сама линия. Вы могли бы сделать

for i, line in enumerate(f): 
    if i == 2: 
     do_stuff_with(line) 
     break # No need to load the rest of the file 

Обратите внимание, что file является именем встроенной команды, так что это плохая идея, чтобы использовать это имя для собственных переменных.

+0

Является ли 'файл' встроенным? Это «NameError» в 3.3. – rlms

+2

Сторона примечания: для итерации только по определенным строкам (например, каждая вторая строка, начиная с третьей строки до 1531), 'itertools.islice' может использоваться:' для строки в itertools.islice (file_object, 3, 1531, 2) '). @ user2387370 'файл' был встроенным в python2. В 'python3' его больше нет и можно безопасно использовать. – Bakuriu

+0

@ user2387370: Они изменили его на Python 3. Я думаю, что новый API находится в модуле 'io'. – user2357112

0

Вы можете перебирать файл любого размера с кодом, который вы указали, и он не должен потреблять значительного объема памяти за пределами самой длинной отдельной строки.

Что касается работы, под капотом, вы можете погрузиться в исходный код для самого Python, чтобы узнать подробности gory. На более высоком уровне просто подумайте, что разработчик файловых объектов в Python решил реализовать линейную итерацию как функцию своего класса.

Многие типы данных сбора данных и интерфейсы ввода-вывода в Python реализуют некоторую форму итерации. Таким образом, конструкция for является наиболее распространенным типом цикла в Python. Вы можете перебирать списки, кортежи и наборы (по элементам), строки (по символам), словари (по ключу), а многие классы (в том числе в стандартных библиотеках, а также в сторонних) реализуют «iterator (coding) protocol «для облегчения такого использования.

Смежные вопросы