04

Двигаемся дальше

Работа с произвольными файлами

Для того что бы обрабатывать данные с лабораторных работ, нужно что бы они как-то попали к вам в программу. Конечно можно просто ввести их непосредтсвенно в код программы (например так, data = [1,2,3,4,5,6,7]), но по многим практическим соброжениям это не удобно и неправильно. Корректным будет хранить данные в отдельных файлах и уметь считывать информацию из них. Способов считывать данные много, о более удобных для использования (но работающих только с определенными форматами файлов) мы поговорим в следующих разделах, а сейчас разберем универсальный способ работы с произвольным файлом.
Файлы можно окрывать в двух режимах:

  • Текстовом: информация в файле интерпретируется как текст, и в данном мы оперируем данными как набором символов, например если в файл написано 123, это не значит что там записанно число 123, а значит что там записаны символы 1, 2, 3.
  • Бинарном: информация в файле интерпретируется как набор байтов и в данном случае мы оперируем отдельными байтами, которые мы потом можем интерперитовать как числа, символы или ещё что-то.
In [4]:
fin = open("example_fit.txt") # Окрываем файл
text = fin.read() # Считываем его целиком
fin.close() # Закрываем файл
text 
Out[4]:
'        x         y    y_error\n0          1.05923   0.0861431\n0.0714286  0.913173  0.0859666\n0.142857   0.954408  0.06095\n0.214286   0.819393  0.0378351\n0.285714   0.91041   0.07267\n0.357143   0.73905   0.0580905\n0.428571   0.80262   0.0656587\n0.5        0.764531  0.0278336\n0.571429   0.782643  0.0450629\n0.642857   0.790794  0.0482949\n0.714286   0.762573  0.0409075\n0.785714   0.8131    0.0640749\n0.857143   0.779934  0.0820886\n0.928571   0.915171  0.082733\n1          1.00332   0.0567224'

Как мы видим считанная из файла информация представлена как строка и для того чтобы получить из неё цифоры её надо будет обработать. Нам необязательно считывать файл целиком, мы можем делать это построчно или посимвольно, считывать данные можно не только с начала файла но и с произвольного места. Обращаю ваше внимание на операцию fin.close(), закрытие файла очень важно, не смотря на то что Python часто относиться к этому либерально, если вы не закроете файл то вы можете потерять данные при записи в файл или может возникнуть проблема с записью в этот файл. Для того что бы не иметь проблем с закрытием файлов нужно использовать контекстный менеджер.

In [ ]:
with open("temp.txt", "w") as fout: # Переменная fout действует внутри контекста open
    fout.write("Текст") # Пишим данные
    # Обрабите внимание что в текстовые файлы мы пишем текст, 
    # поэтому нужно привести числовые данные к строкам

Как видно в этом примере для того что бы открыть файл на запись мы передали второй аргумент в функцию open. "w" означает что файл открыт на запись, при этом сущетсвующующий файл перезаписывается. Сущетсвуют различные режимы записи/чтения файла, если нужно совместить несколько режимов, они указываются вместе, например "rb" - октрывает файл на чтение в бинарном режиме. По умолчанию файл открывается на чтение в текстовом режиме.

Еще не много важных вещей о переменных и об объектах (дополнительный материал)

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

In [6]:
a = [1,2,3]
b = a
print("a : {}".format(a))
print("b : {}".format(b))
b[1] = 10
print("a : {}".format(a))
a : [1, 2, 3]
b : [1, 2, 3]
a : [1, 10, 3]

Мы поменяли что-то в перменной b, а изменилась переменная a? Нет это не правильная точка зрения, и a, и b ссылаются на один и тот же список лежащий в памяти и поэтому неважно через какую переменную мы к нему обращащемся. Если же мы хотит записать в gпеременную b новый объект являющийся копией сущетсвующего объекта, то мы должны использовать методы copy (создает поверхностную копию) и deepcopy (создает полную копию) (о разнице в этих методах можно прочесть здесь).

Так же следует знать что объекты в Python бывают изменяемые и не изменяемые. Они отличаются тем, что содержимое изменяемых объектов может быть изменено (перезаписанно в памяти), а неизменяемых нет. Расмотрим пример:

In [9]:
a = "String" # строка не изменяемый объект
b = a.upper() # Метод upper нужен для перевода данных в верхний регистр
print(a) # Строка a не изменилась
print(b) # Строка b это новый объект строки, никак не связанный с предыдущим
String
STRING
In [7]:
a = [5,4,3,2,1] # список изменемый объект
a.sort() # При сортировке не создался новый список, с отсортированными значениями,
         # а изменился сущетсвующий объект
a
Out[7]:
[1, 2, 3, 4, 5]

Другим существенным отличием в неизменяемых от изменяемых объектов, является их поведение при передачи в функцию.

In [10]:
a = [1,2,3]

print(a)

def change_list(a):
    a.append(0) # Добавляем новый элементв в a
    
change_list(a)
print(a)
[1, 2, 3]
[1, 2, 3, 0]

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

Структуры данных: словари и кортежи

Пришло время познакомится с ещё двумя структурами данных.

Кортежи

Кортежи (tuple) - неизменяемые списки. Для них доступны все операции над списками, не изменяющие список (сложение, умножение на число, методы index() и count() и некоторые другие операции). Можно также по-разному менять элементы местами и так далее.

In [5]:
a = tuple() # создание пустого кортежа
a = () # создание пустого кортежа
c = tuple([1, 2, 3, 4, 5])
с = 1, 2, 3, 4, 5 # Это тоже кортеж
print(c)
c += (1, 2, 3)
print(c)
c = c * 2
print(c)
print(len(c)) # длина кортежа
(1, 2, 3, 4, 5)
(1, 2, 3, 4, 5, 1, 2, 3)
(1, 2, 3, 4, 5, 1, 2, 3, 1, 2, 3, 4, 5, 1, 2, 3)
16

Другим важным свойсвтом кортежа, явлется возможность использовать его для упаковки/распаковки данных.

In [2]:
a, b = 1, 2 # 1,2 это на самом деле кортеж, который  можно распаковать по отдельным переменным
a, b = b, a # меняем значения переменных местами
In [3]:
def fun(a,b):
    """
    Так же кортеж можно использовать
    что бы вернуть из функции несколько аргументов
    """
    a = 1
    b = 2
    return a, b

c = (1,2)
a, b = fun(*c) # `*c` позволяет распаковать значения из кортежа `с` как аргументы функции

Словари

Словари (они же карты (map), ассоциативные массивы и хэш-таблицы) --- структра, позволяющая организовтаь доступ к данным по ключу. Данные в словаре хранятся в формате ключ – значение.

In [4]:
d = {'a': 1, 'b': 2}
print(d)
d['a'] = 3
print(d)
print(d.keys())
{'a': 1, 'b': 2}
{'a': 3, 'b': 2}
dict_keys(['a', 'b'])
In [6]:
def fun(a=1,b=2):
    """
    Так же кортеж можно использовать
    что бы вернуть из функции несколько аргументов
    """
    return a, b

fun(**d) # `**d` позволяет распаковать значения из словаря `d` как именнованые аргументы функции
Out[6]:
(3, 2)

Больше полезных модулей, типов, структур данных, методов, свойств можно найти в интернете. Гуглите!

^Наверх
Вниз