Определение основных функций в Python

Определение основных функций в Python

Многие языки программирования имеют специальную функцию, которая автоматически выполняется, когда операционная система запускает программу. Эта функция обычно называетсяmain() и должна иметь определенный тип возвращаемого значения и аргументы в соответствии со стандартом языка. С другой стороны, интерпретатор Python выполняет сценарии, начиная с верхней части файла, и нет никакой специальной функции, которую Python выполняет автоматически.

Тем не менее, наличие определенной начальной точки для выполнения программы полезно для понимания того, как работает программа. Программисты Python придумали несколько соглашений для определения этой отправной точки.

К концу этой статьи вы поймете:

  • Что такое специальная переменная__name__ и как ее определяет Python

  • Почему вы хотите использоватьmain() в Python

  • Какие соглашения существуют для определенияmain() в Python

  • Каковы лучшие практики для того, какой код поместить в вашmain()

Free Bonus:Click here to get access to a chapter from Python Tricks: The Book, который демонстрирует вам лучшие практики Python на простых примерах, которые вы можете мгновенно применить для написания более красивого кода Pythonic.

Основной Python main ()

В некоторых скриптах Python вы можете увидеть определение функции и условный оператор, который выглядит следующим образом:

def main():
    print("Hello World!")

if __name__ == "__main__":
    main()

В этом коде есть функция с именемmain(), которая печатает фразуHello World!, когда интерпретатор Python выполняет ее. Существует также условный оператор (илиif), который проверяет значение__name__ и сравнивает его со строкой"__main__". Когда операторif оценивается какTrue, интерпретатор Python выполняетmain(). Вы можете узнать больше об условных операторах вConditional Statements in Python.

Этот шаблон кода довольно часто встречается в файлах Python, которые должны бытьexecuted as a script иimported in another module. Чтобы понять, как будет выполняться этот код, вы должны сначала понять, как интерпретатор Python устанавливает__name__ в зависимости от того, как выполняется код.

Режимы выполнения в Python

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

  1. Вы можете выполнить файл Python какscript с помощью командной строки.

  2. Вы можетеimport код из одного файла Python в другой файл или в интерактивный интерпретатор.

Вы можете узнать больше об этих подходах вHow to Run Your Python Scripts. Независимо от того, какой способ выполнения кода вы используете, Python определяет специальную переменную с именем__name__, которая содержит строку, значение которой зависит от того, как используется код.

Мы будем использовать этот пример файла, сохраненного какexecution_methods.py, чтобы исследовать, как поведение кода изменяется в зависимости от контекста:

print("This is my file to test Python's execution methods.")
print("The variable __name__ tells me which context this file is running in.")
print("The value of __name__ is:", repr(__name__))

В этом файле определены три вызоваprint(). Первые два печатают несколько вводных фраз. Третийprint() сначала напечатает фразуThe value of __name__ is, а затем напечатает представление переменной__name__, используя встроенный Pythonrepr().

В Pythonrepr() отображает представление объекта для печати. В этом примереrepr() используется, чтобы подчеркнуть, что значение__name__ является строкой. Вы можете узнать больше оrepr() вPython documentation.

В этой статье вы увидите словаfile,module иscript. Практически между ними нет большой разницы. Тем не менее, есть небольшие различия в значении, которые подчеркивают цель фрагмента кода:

  1. File: Обычно файл Python - это любой файл, содержащий код. Большинство файлов Python имеют расширение.py.

  2. Script: Сценарий Python - это файл, который вы собираетесь запустить из командной строки для выполнения задачи.

  3. Module: Модуль Python - это файл, который вы собираетесь импортировать из другого модуля или сценария, или из интерактивного интерпретатора. Вы можете узнать больше о модулях вPython documentation.

Это различие также обсуждается вHow to Run Your Python Scripts.

Выполнение из командной строки

При таком подходе вы хотите выполнить ваш скрипт Python из командной строки.

Когда вы выполняете скрипт, вы не сможете интерактивно определить код, который выполняет интерпретатор Python. Детали того, как вы можете запускать Python из командной строки, не так важны для целей этой статьи, но вы можете расширить поле ниже, чтобы узнать больше о различиях между командной строкой в ​​Windows, Linux и macOS.

Теперь вы должны выполнить сценарийexecution_methods.py из командной строки, как показано ниже:

$ python3 execution_methods.py
This is my file to test Python's execution methods.
The variable __name__ tells me which context this file is running in.
The value of __name__ is: '__main__'

В этом примере вы можете видеть, что__name__ имеет значение'__main__', где символы кавычек (') говорят вам, что значение имеет строковый тип.

Помните, что в Python нет разницы между строками, определенными одинарными кавычками (') и двойными кавычками ("). Вы можете узнать больше об определении строк вBasic Data Types in Python.

Вы найдете идентичный вывод, если включитеshebang line в свой скрипт и выполните его напрямую (./execution_methods.py) или воспользуетесь магией%run в IPython или Jupyter Notebooks.

Вы также можете увидеть скрипты Python, выполняемые из пакетов, добавив аргумент-m к команде. Чаще всего вы увидите эту рекомендацию, когда используетеpip:python3 -m pip install package_name.

Добавление аргумента-m запускает код в модуле__main__.py пакета. Вы можете найти дополнительную информацию о файле__main__.py вHow to Publish an Open-Source Python Package to PyPI.

Во всех трех случаях__name__ имеет одно и то же значение: строка'__main__'.

Technical detail: В документации Python конкретно указано, когда__name__ будет иметь значение'__main__':

__name__ модуля устанавливается равным'__main__' при чтении из стандартного ввода, сценария или из интерактивной подсказки. (https://docs.python.org/3/library/main.html [Источник])

__name__ хранится в глобальном пространстве имен модуля вместе с__doc__,__package__ и другими атрибутами. Вы можете прочитать больше об этих атрибутах вPython Data Model documentation и, особенно для модулей и пакетов, вPython Import documentation.

Импорт в модуль или интерактивный интерпретатор

Теперь давайте рассмотрим второй способ, которым интерпретатор Python выполнит ваш код: импорт. Когда вы разрабатываете модуль или скрипт, вы, скорее всего, захотите воспользоваться преимуществами модулей, которые уже созданы кем-то другим, что вы можете сделать с помощью ключевого словаimport.

Во время процесса импорта Python выполняет операторы, определенные в указанном модуле (но толькоfirst, когда вы импортируете модуль). Чтобы продемонстрировать результаты импорта файлаexecution_methods.py, запустите интерактивный интерпретатор Python, а затем импортируйте файлexecution_methods.py:

>>>

>>> import execution_methods
This is my file to test Python's execution methods.
The variable __name__ tells me which context this file is running in.
The value of __name__ is: 'execution_methods'

В этом выводе кода вы можете видеть, что интерпретатор Python выполняет три вызоваprint(). Первые две строки вывода точно такие же, как при запуске файла в виде сценария в командной строке, потому что ни в одной из первых двух строк нет переменных. Однако есть разница в выходе третьегоprint().

Когда интерпретатор Python импортирует код, значение__name__ устанавливается таким же, как имя импортируемого модуля. Вы можете увидеть это в третьей строке выше. __name__ имеет значение'execution_methods', которое является именем файла.py, из которого Python импортирует.

Обратите внимание, что если вы сноваimport модуль без выхода из Python, выход не будет.

Note: Для получения дополнительной информации о том, как импорт работает в Python, ознакомьтесь сofficial documentation, а такжеAbsolute vs Relative Imports in Python.

Лучшие практики для основных функций Python

Теперь, когда вы можете увидеть различия в том, как Python обрабатывает свои различные режимы выполнения, полезно узнать некоторые рекомендации. Они будут применяться всякий раз, когда вы захотите написать код, который можно запустить как импорт скриптаand в другой модуль или интерактивный сеанс.

Вы узнаете о четырех передовых практиках, чтобы убедиться, что ваш код может служить двойной цели:

  1. Поместите большую часть кода в функцию или класс.

  2. Используйте__name__ для управления выполнением вашего кода.

  3. Создайте функцию с именемmain(), которая будет содержать код, который вы хотите запустить.

  4. Вызов других функций изmain().

Поместите большую часть кода в функцию или класс

Помните, что интерпретатор Python выполняет весь код в модуле при импорте модуля. Иногда код, который вы пишете, будет иметь побочные эффекты, которые вы хотите, чтобы пользователь контролировал, такие как:

  • Выполнение вычисления, которое занимает много времени

  • Запись в файл на диске

  • Печать информации, которая загромождает терминал пользователя

В этих случаях вы хотите, чтобы пользователь контролировал запуск выполнения этого кода вместо того, чтобы позволить интерпретатору Python выполнять код при импорте вашего модуля.

Поэтому лучше всегоinclude most code inside a function or a class. Это связано с тем, что, когда интерпретатор Python встречает ключевые словаdef илиclass, он сохраняет эти определения только для дальнейшего использования и фактически не выполняет их, пока вы ему не скажете.

Сохраните приведенный ниже код в файл с именемbest_practices.py, чтобы продемонстрировать эту идею:

 1 from time import sleep
 2
 3 print("This is my file to demonstrate best practices.")
 4
 5 def process_data(data):
 6     print("Beginning data processing...")
 7     modified_data = data + " that has been modified"
 8     sleep(3)
 9     print("Data processing finished.")
10     return modified_data

В этом коде вы сначала импортируетеsleep() изtime module.

sleep() приостанавливает интерпретатор на количество секунд, которое вы указываете в качестве аргумента, и создает функцию, выполнение которой для этого примера занимает много времени. Затем вы используетеprint(), чтобы напечатать предложение, описывающее цель этого кода.

Затем вы определяете функцию с именемprocess_data(), которая выполняет пять функций:

  1. Выводит некоторый вывод, чтобы сообщить пользователю, что обработка данных начинается

  2. Изменяет входные данные

  3. Приостанавливает выполнение на три секунды, используяsleep()

  4. Выводит некоторый вывод, чтобы сообщить пользователю, что обработка завершена

  5. Возвращает измененные данные

Запустите файл лучших практик в командной строке

Теперь, что произойдет, когда вы запустите этот файл как скрипт в командной строке?

Интерпретатор Python выполнит строкиfrom time import sleep иprint(), которые находятся вне определения функции, затем он создаст определение функции с именемprocess_data(). Затем сценарий завершится без каких-либо дополнительных действий, поскольку в сценарии нет кода, выполняющегоprocess_data().

Блок кода ниже показывает результат запуска этого файла в виде скрипта:

$ python3 best_practices.py
This is my file to demonstrate best practices.

Результат, который мы видим здесь, является результатом первогоprint(). Обратите внимание, что импорт изtime и определениеprocess_data() не приводят к выходным данным. В частности, выходы вызововprint(), которые находятся внутри определенияprocess_data(), не печатаются!

Импортируйте файл рекомендаций в другой модуль или интерактивный интерпретатор

Когда вы импортируете этот файл в интерактивном сеансе (или другом модуле), интерпретатор Python будет выполнять те же действия, что и при запуске файла в виде скрипта.

После того, как интерпретатор Python импортирует файл, вы можете использовать любые переменные, классы или функции, определенные в импортированном вами модуле. Чтобы продемонстрировать это, мы будем использовать интерактивный интерпретатор Python. Запустите интерактивный интерпретатор и введитеimport best_practices:

>>>

>>> import best_practices
This is my file to demonstrate best practices.

Единственный результат импорта файлаbest_practices.py - это первый вызовprint(), определенный внеprocess_data(). Импорт изtime и определениеprocess_data() не приводят к выходным данным, как и при выполнении кода из командной строки.

Используйтеif __name__ == "main" для управления выполнением вашего кода

Что, если вы хотите, чтобыprocess_data() выполнялся, когда вы запускаете скрипт из командной строки, но не когда интерпретатор Python импортирует файл?

Вы можетеuse the if __name__ == "main" idiom to determine the execution context и условно запуститьprocess_data() только тогда, когда__name__ равно"__main__". Добавьте приведенный ниже код в конец файлаbest_practices.py:

11 if __name__ == "__main__":
12     data = "My data read from the Web"
13     print(data)
14     modified_data = process_data(data)
15     print(modified_data)

В этом коде вы добавили условный оператор, который проверяет значение__name__. Это условие будет оцениваться какTrue, когда__name__ равно строке"__main__". Помните, что специальное значение"__main__" для переменной__name__ означает, что интерпретатор Python выполняет ваш сценарий, а не импортирует его.

Внутри условного блока вы добавили четыре строки кода (строки 12, 13, 14 и 15):

  • Lines 12 and 13: Вы создаете переменнуюdata, в которой хранятся данные, полученные из Интернета, и распечатываете их.

  • Line 14: Вы обрабатываете данные.

  • Line 15: Вы печатаете измененные данные.

Теперь запустите сценарийbest_practices.py из командной строки, чтобы увидеть, как изменится вывод:

$ python3 best_practices.py
This is my file to demonstrate best practices.
My data read from the Web
Beginning data processing...
Data processing finished.
My data read from the Web that has been modified

Во-первых, выходные данные показывают результат вызоваprint() внеprocess_data().

После этого печатается значениеdata. Это произошло потому, что переменная__name__ имеет значение"__main__", когда интерпретатор Python выполняет файл как сценарий, поэтому условный оператор оценивается какTrue.

Затем ваш скрипт вызвалprocess_data() и передалdata для модификации. Когдаprocess_data() выполняется, он выводит некоторые сообщения о состоянии. Наконец, печатается значениеmodified_data.

Теперь вы должны проверить, что происходит при импорте файлаbest_practices.py из интерактивного интерпретатора (или другого модуля). Пример ниже демонстрирует эту ситуацию:

>>>

>>> import best_practices
This is my file to demonstrate best practices.

Обратите внимание, что вы получаете то же поведение, что и до добавления условного выражения в конец файла! Это связано с тем, что переменная__name__ имела значение"best_practices", поэтому Python не выполнял код внутри блока, включаяprocess_data(), потому что условный оператор оценивается какFalse.

Создайте функцию с именем main (), которая будет содержать код, который вы хотите запустить

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

Многие языки, такие как C, C +, Java и некоторые другие, определяют специальную функцию, которая должна вызываться `+ main ()`, которую операционная система автоматически вызывает при выполнении скомпилированной программы. Эту функцию часто называютentry point, потому что именно здесь выполнение входит в программу.

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

Хотя Python не придает никакого значения функции с именемmain(), в любом случае лучше всего использоватьname the entry point function main(). Таким образом, любые другие программисты, которые читают ваш сценарий, сразу же узнают, что эта функция является отправной точкой кода, который выполняет основную задачу сценария.

Кроме того,main() должен содержать любой код, который вы хотите запустить, когда интерпретатор Python выполняет файл. Это лучше, чем помещать код непосредственно в условный блок, потому что пользователь может повторно использовать main (), если они импортируют ваш модуль.

Измените файлbest_practices.py так, чтобы он выглядел как код ниже:

 1 from time import sleep
 2
 3 print("This is my file to demonstrate best practices.")
 4
 5 def process_data(data):
 6     print("Beginning data processing...")
 7     modified_data = data + " that has been modified"
 8     sleep(3)
 9     print("Data processing finished.")
10     return modified_data
11
12 def main():
13     data = "My data read from the Web"
14     print(data)
15     modified_data = process_data(data)
16     print(modified_data)
17
18 if __name__ == "__main__":
19     main()

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

Вызов других функций из main ()

Другая распространенная практика в Python - этоhave main() execute other functions, а не включение кода выполнения задачи вmain(). Это особенно полезно, когда вы можете составить общую задачу из нескольких небольших подзадач, которые могут выполняться независимо.

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

  1. Считывает файл данных из источника, который может быть базой данных, файлом на диске или веб-API

  2. Обрабатывает данные

  3. Записывает обработанные данные в другое место

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

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

Измените файлbest_practices.py так, чтобы он выглядел как код ниже:

 1 from time import sleep
 2
 3 print("This is my file to demonstrate best practices.")
 4
 5 def process_data(data):
 6     print("Beginning data processing...")
 7     modified_data = data + " that has been modified"
 8     sleep(3)
 9     print("Data processing finished.")
10     return modified_data
11
12 def read_data_from_web():
13     print("Reading data from the Web")
14     data = "Data from the web"
15     return data
16
17 def write_data_to_database(data):
18     print("Writing data to a database")
19     print(data)
20
21 def main():
22     data = read_data_from_web()
23     modified_data = process_data(data)
24     write_data_to_database(modified_data)
25
26 if __name__ == "__main__":
27     main()

В этом примере кода первые 10 строк файла имеют то же содержимое, что и раньше. Второе определение функции в строке 12 создает и возвращает некоторые примерные данные, а третье определение функции в строке 17 имитирует запись измененных данных в базу данных.

В строке 21 определяетсяmain(). В этом примере вы изменилиmain() так, чтобы он по очереди вызывал функции чтения, обработки и записи данных.

Во-первых,data создается изread_data_from_web(). Этотdata передается вprocess_data(), который возвращаетmodified_data. Наконец,modified_data передается вwrite_data_to_database().

Последние две строки сценария - это условный блок, который проверяет__name__ и запускаетmain(), если операторif равенTrue.

Теперь вы можете запустить весь конвейер обработки из командной строки, как показано ниже:

$ python3 best_practices.py
This is my file to demonstrate best practices.
Reading data from the Web
Beginning data processing...
Data processing finished.
Writing processed data to a database
Data from the web that has been modified

На выходе этого выполнения вы можете видеть, что интерпретатор Python выполнилmain(), который выполнилread_data_from_web(),process_data() иwrite_data_to_database(). Однако вы также можете импортировать файлbest_practices.py и повторно использоватьprocess_data() для другого источника входных данных, как показано ниже:

>>>

>>> import best_practices as bp
This is my file to demonstrate best practices.
>>> data = "Data from a file"
>>> modified_data = bp.process_data(data)
Beginning data processing...
Data processing finished.
>>> bp.write_data_to_database(modified_data)
Writing processed data to a database
Data from a file that has been modified

В этом примере вы импортировалиbest_practices и сократили имя доbp для этого кода.

В процессе импорта интерпретатор Python выполнил все строки кода в файлеbest_practices.py, поэтому в выходных данных отображается строка, объясняющая назначение файла.

Затем вы сохранили данные из файла вdata вместо чтения данных из Интернета. Затем вы повторно использовалиprocess_data()+`and `+write_data_to_database() из файлаbest_practices.py. В этом случае вы воспользовались преимуществом повторного использования вашего кода вместо определения всей логики вmain().

Резюме рекомендаций по основным функциям Python

Вот четыре ключевых передовых метода использованияmain() в Python, которые вы только что видели:

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

  2. Используйте разные значения__name__, чтобы определить контекст и изменить поведение вашего кода с помощью условного оператора.

  3. Вы должны назвать свою точку входа functionmain(), чтобы сообщить о назначении функции, даже если Python не придает особого значения функции с именемmain().

  4. Если вы хотите повторно использовать функциональные возможности вашего кода, определите логику в функциях внеmain() и вызовите эти функции в пределахmain().

Заключение

Поздравляем! Теперь вы знаете, как создавать функции Pythonmain().

Вы узнали следующее:

  • Знание значения переменной__name__ важно для написания кода, который служит двойной цели: исполняемый скрипт и импортируемый модуль.

  • __name__ принимает разные значения в зависимости от того, как вы выполняли свой файл Python. __name__ будет равно:

    • "__main__", когда файл выполняется из командной строки, или с помощьюpython -m (для выполнения файла__main__.py пакета)

    • Имя модуля, если модуль импортируется

  • Программисты Python разработали ряд хороших методов, которые можно использовать, когда вы хотите разработать повторно используемый код.

Теперь вы готовы написать отличный код функции Pythonmain()!

Related