Этим постом я открываю серию, посвященную тому, как облегчить себе рабочие будни, программируя на Python. Для тех, кто занят или нетерпелив, я написал выжимку.
ABSTRACT
По большей части мы будем говорить о функциях и модулях. Модульное программирование расширяет возможности классического процедурного. Понимание модулей в Python требует знаний из теории ООП, но здесь их будет по минимуму. Тем не менее, я надеюсь, что ваш функционал значительно расширится после знакомства с идеями, которыми я хочу с вами поделиться.
I. Цели и методы
Так как наша задача состоит в том, чтобы сделать работу более удобной и легкой, то нам придётся наводить порядок в коде. Мы должны (по идее так должно быть каждый раз, когда мы программируем) писать такой код, который:
а) легко читать (не только нам, но и коллеге Петру)
б) легко поддерживать/модифицировать
в) легко "заводить" программу-клон с нуля (отдохнувшие пару месяцев от программы люди меня поймут)
Основная парадигма состоит в разделении функционала по разным модулям и их использование в основной программе. При этом каждый модуль содержит набор типовых функций, которые нам необходимы в трудовой жизни. Получается, что программа собирается из функций, которые хранятся в модулях. Собственно мы будем делать почти тоже самое, что делает, скажем numpy. Такая схема позволяет быстро собрать главную программу из других программных единиц. Мне это очень напоминает конструктор, а вам?
II. Модуль. Инструкция import
Лучше, конечно, прочитать соответствующий раздел в учебнике (бумажный или электронный ресурс), многое тогда пойдёт легче или полетит элементарно. Итак, модуль - это такой же файл с расширением "py", что и основная программа, но структурно это не главная программа. Проверить является ли файл главной программой можно так:
if __name__ == '__main__':
print 'It is the main program' # это главная программа
else:
print 'It is a module' # 'это модуль
Вызвать модуль можно через import. Это инструкция позволяет нам соединять файлы или их кусочки в одну программу. В модуль мы будем помещать функции, которые далее станут атрибутами данного модуля. Атрибут "sum" модуля numpy мы вызываем, когда пишем:
xsum = np.sum(x, axis=1)
# -*- coding: utf-8 -*-
def minix(x):
pass
def maxix(x):
pass
def sumix(x):
pass
Не сомневаюсь, что каждый читатель блога может заполнить "тела" функций кодом нахождения минимума, максимума и суммы последовательности. Тогда тело главной программы, согласно изложенной выше схеме, будет выглядеть примерно так:
# -*- coding: utf-8 -*-
import mathik as mk
t = [0,-1,4,8,15,-2,5,7,-6,0,10]
print 'MAX: %d' % (mk.maxix(t))
print 'MIN: %d' % (mk.minix(t))
print 'SUM: %d' % (mk.sumix(t))
III. Где хранятся модули? Пути поиска модуля
Идея понятна. Стоит отметить, что необходимые для импорта модули интерпретатор ищет либо в этой же папке, где лежит основная программа, либо в других местах (папках). Получить полный список путей, в которых выполняется поиск подключаемого модуля, позволяет модуль sys:
import sys
print sys.path # список путей к папкам, из которых модуль будет "виден"
Для поиска мест, откуда можно поймать модуль, в python есть специальная переменная среды - PYTHONPATH. Если вы поместите туда адрес каталога (папки) с созданными вами модулями, то можно спокойно их вызывать отовсюду. PYTHONPATH нужно искать в переменных среды вашей операционной системы. Для Linux - тут или на русском, а для Windows.
Иногда полезно добавить в список sys.path путь к модулю только на время работы программы. Для этого можно динамически добавлять в самой программе (естественно, до вызова необходимого модуля) строку к списку sys.path:
import sys
my_modulepath = 'C:/My_path/'
sys.path.append()
print sys.path
Когда закроется интерпретатор, забудется и добавленный путь.
IV. Импорт модуля в модуль. Горизонтальные связи модулей
Но что если нам этого мало и мы хотим график? Имеет смысл создать ещё один модуль "paint2D.py", где будут лежать подпрограммы для 2D рисования. Скажем, такой:
# -*- coding: utf-8 -*-
import mathik as mk # вызываем уже сделанный модуль. Будем использовать его атрибуты
import matplotlib.pyplot as plt
def graph(x):
plt.plot(x,'g--')
plt.plot(x.index(mk.maxix(x)),mk.maxix(x),'ro')
plt.plot(x.index(mk.maxix(x)),mk.maxix(x),'bo')
plt.text(5, 10, '%s' % str(mk.sumix(x)))
plt.show()
В основной программе код будет такой:
# -*- coding: utf-8 -*-
import paint2D as p2d
x = [0,1,2,3,4,5,-6,6,7,8]
p2d.graph(x)
Если последовательность нам интересна как массив или временной ряд, то можно добавить в модуль "paint2D.py" функции для рисования гистограмм, ящиков с усами и спектрограмм.
Если нам понадобится отобразить информацию на карте, имеет смысл завести модуль "mymap.py" и т.д.
V. Преимущества предложенной методики
Через некоторое время у вас будет набор таких модулей, которые вам необходимы для работы. Чтобы собрать программу вам нужно будет подключить эти модули и воспользоваться необходимыми функциями. Это намного удобнее, чем писать небольшие программки или складировать в главную программу все подпрограммы (те, кто знают Фортран на windows, поймут меня). Главная программа получается краткая, нарядная, тестировать её проще (отключая и подсоединяя последовательно нужные модули-функции), будет меньше случайных ошибок, так как большую часть кода вы уже протестируете при сборке других программ. В общем, сплошной кайф, а не система!
III. Где хранятся модули? Пути поиска модуля
Идея понятна. Стоит отметить, что необходимые для импорта модули интерпретатор ищет либо в этой же папке, где лежит основная программа, либо в других местах (папках). Получить полный список путей, в которых выполняется поиск подключаемого модуля, позволяет модуль sys:
import sys
print sys.path # список путей к папкам, из которых модуль будет "виден"
Для поиска мест, откуда можно поймать модуль, в python есть специальная переменная среды - PYTHONPATH. Если вы поместите туда адрес каталога (папки) с созданными вами модулями, то можно спокойно их вызывать отовсюду. PYTHONPATH нужно искать в переменных среды вашей операционной системы. Для Linux - тут или на русском, а для Windows.
Иногда полезно добавить в список sys.path путь к модулю только на время работы программы. Для этого можно динамически добавлять в самой программе (естественно, до вызова необходимого модуля) строку к списку sys.path:
import sys
my_modulepath = 'C:/My_path/'
sys.path.append()
print sys.path
import my_module_which_is_in_my_modulepath
Когда закроется интерпретатор, забудется и добавленный путь.
IV. Импорт модуля в модуль. Горизонтальные связи модулей
Но что если нам этого мало и мы хотим график? Имеет смысл создать ещё один модуль "paint2D.py", где будут лежать подпрограммы для 2D рисования. Скажем, такой:
# -*- coding: utf-8 -*-
import mathik as mk # вызываем уже сделанный модуль. Будем использовать его атрибуты
import matplotlib.pyplot as plt
def graph(x):
plt.plot(x,'g--')
plt.plot(x.index(mk.maxix(x)),mk.maxix(x),'ro')
plt.plot(x.index(mk.maxix(x)),mk.maxix(x),'bo')
plt.text(5, 10, '%s' % str(mk.sumix(x)))
plt.show()
В основной программе код будет такой:
# -*- coding: utf-8 -*-
import paint2D as p2d
x = [0,1,2,3,4,5,-6,6,7,8]
p2d.graph(x)
Если последовательность нам интересна как массив или временной ряд, то можно добавить в модуль "paint2D.py" функции для рисования гистограмм, ящиков с усами и спектрограмм.
Если нам понадобится отобразить информацию на карте, имеет смысл завести модуль "mymap.py" и т.д.
V. Преимущества предложенной методики
Через некоторое время у вас будет набор таких модулей, которые вам необходимы для работы. Чтобы собрать программу вам нужно будет подключить эти модули и воспользоваться необходимыми функциями. Это намного удобнее, чем писать небольшие программки или складировать в главную программу все подпрограммы (те, кто знают Фортран на windows, поймут меня). Главная программа получается краткая, нарядная, тестировать её проще (отключая и подсоединяя последовательно нужные модули-функции), будет меньше случайных ошибок, так как большую часть кода вы уже протестируете при сборке других программ. В общем, сплошной кайф, а не система!