Питон: работа с файлами

На серьезных олимпиадах, а также во многих других ситуациях вам надо читать данные не с клавиатуры, а из файла, и выводить данные в файл, а не на "экран". В таком случае вы должны знать имена этих файлов; в задачах они, как правило, указаны, на этом сайте имена файлов почти всегда — input.txt для входных данных и output.txt для выходных.

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

Ввод данных

Самый простой способ ввести данные из файла в питоне — это сразу считать их в массив строк. Это делается так:

data = open("input.txt", "r").readlines()

Здесь input.txt — файл, откуда надо считать данные, параметр "r" указывает, что вы собираетесь именно читать (read) данные, а не записывать (write, см. ниже). Команда open, как говорят, «открывает файл на чтение», а команда readlines считывает весь файл в массив строк.

Теперь data — это массив строк, каждый элемент которого — это очередная строка из входного файла. Например, если в файле было написано

1 2 3
4 5 6
some text

то data будет содержать массив ["1 2 3\n", "4 5 6\n", "some text\n"]. (Здесь "\n" — это символ перевода строки, он будет на конце каждой строки массива data, кроме, возможно, последней. Если вы считываете числа, то можете о нем не беспокоиться, а если считываете строки и он вам мешает, то, как правило, от него можно избавиться командой a = a.rstrip("\n"), где a — строка, у которого вы хотите его убрать.)

Каждый элемент массива data — это как результат отдельной команды input(), которой вы пользовались для чтения с клавиатуры. Поэтому дальше вы пишете программу так же, как писали и раньше, но вместо каждого очередного обращения к input() вы обращаетесь к очередному элементу массива data. В простых случаях все просто, в более сложных вам надо аккуратно подсчитывать, к какому именно элементу массива вам надо обратиться.

Пример. Пусть во входном файле два числа по одному на строке. Их считываем так (здесь и далее слева — пример чтения с клавиатуры, справа — из файла):

a = int(input())
b = int(input())
data = open("input.txt", "r").readlines()
a = int(data[0])
b = int(data[1])

Если же два числа в одной строке:

a, b = map(int, input().split())
data = open("input.txt", "r").readlines()
a, b = map(int, data[0].split())

Более сложный пример: сначала число N, а потом N строк по одному числу в каждой:

n = int(input())
for i in range(n):
    x = int(input())
    #... что-то делаем с x
data = open("input.txt", "r").readlines()
n = int(data[0])
for i in range(n):
    x = int(data[i + 1])
    #... что-то делаем с x

Обратите внимание на то, что здесь написано i + 1 — потому что в первой (нулевой) строке было n.

Вывод

Проще всего выводить данные — записав их в одну большую строку и выведя эту строку. Вывод строки в файл делается так:

open("output.txt", "w").write(s)

здесь s — строка, которую нужно вывести. Это должна быть именно строка, а не число и т.д. Используйте функцию str, чтобы превратить что угодно в строку, вручную добавляйте пробелы и переводы строк (перевод строки записывается так: "\n").

Пример: пусть надо вывести два числа в одну строку:

open("output.txt", "w").write(str(a) + " " + str(b))

Пусть надо вывести два числа на отдельных строках:

open("output.txt", "w").write(str(a) + "\n" + str(b))

Пусть надо вывести массив чисел по одному числу на строке:

s = ""
for x in a:
    s = s + str(x) + "\n"
open("output.txt", "w").write(s)

или проще, используя строковую магию:

open("output.txt", "w").write("\n".join(a))

Имейте в виду, что такой вызов должен быть только один раз. Если вы хотите вызывать функцию write несколько раз, то надо суметь вызвать функцию open только один раз. Рекомендуемый вариант — такой:

with open("output.txt", "w") as f:
    f.write("1")
    f.write("2")