Многие python разработчики пишут свои модули и большинство из них часто не задумываются об их структуре. В результате возникает ситуация, что структура модулей может отличаться у разных разработчиков, что снижает читабельность кода и преемственность функционала другими разработчиками. При работе над крупным проектами, такое недопустимо.
Обычно при создании собственных новых модулей, рекомендуется их формировать стандартным образом, с использованием информации, представленной ниже.
Вся основная логика модуля заключена в отдельные функции или классы. На глобальном уровне могут быть объявлены только константы или необходимые для инициализации модуля операции.
1MOD_CONST = 15
2print(MOD_CONST)
3
4def get_sum(x, y):
5 return (x + y) * MOD_CONST
6
7a, b = 1, 2
8print(get_sum(a, b))
Выше представлен пример плохой структуры модуля. В нем содержаться лишние функции print, а также объявлены не константные переменные a и b, которые проверяют работу функции get_sum.
Ниже представлено более правильное исполнение данного модуля. Если планируется запускать модуль как самостоятельный скрипт, то должны быть определена точка входа в модуль в нее записаны инструкции. В python такой конструкцией является if __name__ == '__main__':
1MOD_CONST = 15
2
3def get_sum(x, y):
4 return (x + y) * MOD_CONST
5
6if __name__ == '__main__':
7 print(MOD_CONST)
8 a, b = 1, 2
9 print(get_sum(a, b))
Как правило, в блок if __name__ == '__main__' заносят все вызовы функций и вывод информации на стандартный поток вывода. Ещё один вариант — создать отдельную main() функцию, переписав в неё всю логику при запуске, и вызывать её в данном блоке. Как это работает? Ваш скрипт может выполняться и самостоятельно, а может быть импортирован как модуль другим скриптом. Чтобы выделить код, который не должен выполняться при импорте его следует поместить в условный оператор с условием if __name__ == '__main__':
Каждый скрипт при запуске получает от интерпретатора имя, которое хранится в специальной переменной __name__, которая будет равна "__main__", только если файл запускается как основная программа, и выставляется равной имени модуля при импорте модуля. То есть условие if __name__ == '__main__' проверяет, был ли файл запущен напрямую.
Хорошая структура модуля выглядит следующим образом:
В качестве примера использования Docstring модуля, представлен пример ниже. Он применим и для многих стандартных функций.Чтобы вывести значение описания после импорта используется стандартная функция help().
1import os
2
3help(os)
В результате получим:
1Help on module os:
2NAME os - OS routines for NT or Posix depending on what system we're on.
3
4DESCRIPTION This exports:
5- all functions from posix or nt, e.g. unlink, stat, etc.
6- os.path is either posixpath or ntpat
7- os.name is either 'posix' or 'nt'
8- os.curdir is a string representing the current directory (always '.')
9- os.pardir is a string representing the parent directory (always '..')
10- os.sep is the (or a most common) pathname separator ('/' or '\\')
11- os.extsep is the extension separator (always '.')
12- os.altsep is the alternate pathname separator (None or '/')
13- os.pathsep is the component separator used in $PATH etc
14- os.linesep is the line separator in text files ('\r' or '\n' or '\r\n')
15- os.defpath is the default search path for executables
16- os.devnull is the file path of the null device ('/dev/null', etc.) Programs that import and use 'os' stand a better chance of being portable between different platforms…
Ниже представлен пример модуля с подобной структурой.
1"""Описание нового модуля, вызываемое с помощью стандартной функции help()."""
2
3import os
4import math
5import pandas as pd
6import numpy as np
7import my_module
8
9MOD_CONST = 15
10
11def main():
12 print(MOD_CONST)
13 some_func()
14
15def some_func():
16 print(os.path.abspath())
17 df = pd.read_csv('test.csv')
18 print(df.head())
19
20if __name__ == '__main__':
21 main()
В начале модуля представлено описание того, что он выполняет, так называемый docstring. Затем происходит импорт необходимых библиотек. Далее идет объявление констант.
Следом идет инициализация модуля, т.е. функция содержащая код, который будет выполняться при непосредственном запуске модуля. Делается это из-за того, что модуль может содержать большое количество вспомогательных функций. И чтобы не искать основную логику работы модуля по многочисленным строкам кода или прокрутки файла до блока if __name__ == '__main__':, который находиться в самом конце, её выносят в отдельную функцию и ставят на первое место.
Далее идет область определения функций и классов, которые необходимы для работы с модулями. И в конце блок if __name__ == '__main__':, содержащий код, который не должен выполняться при импорте, а только при непосредственном запуске. Заканчиваться модуль всегда пустой строкой.