Функции – это незаменимая вещь в процедурном (обычном) и, тем более, в функциональном программировании (которое мы будем изучать после прохождения базового курса). Функции позволяют значительно сократить код и сделать его более читаемым, структурировать его логически.
Все команды (операторы) языка по сути своей являются ничем иным, как функциями. Мы научимся писать собственные функции, но те, функции, которые встроены в язык, уже были написаны заранее и хранятся в библиотеке языка. Какие-то из встроенных функций доступны сразу, какие-то необходимо импортировать из определенных модулей.
Напоминаем, что есть разница между понятиями «функция» и «метод». Надеюсь, вы помните, что это такое.
Давайте в качестве примера напишем простейшую функцию, которая при ее вызове будет выводить на экран случайное целое число от 1 до 100. Тут стоит сказать, что для создания функции необходимо написать инструкцию def перед названием функции. Только в таком случае интерпретатор понимает, что мы создаем функцию.
Кроме того, как и инструкция import, с которой мы познакомились ранее, от основного кода программы код функции по правилам Python должен отделяться двумя пустыми строками. Если же мы используем и import, и def, то и между ними оставляются две пустые строки. Также если используется несколько функций, то и между ними предписывается оставлять по две строки. Все это необходимо для лучшей читаемости кода.
Итак, в нашем случае мы будем использовать и import (для импорта модуля random), и def (для создания своей функции). Вот как это должно выглядеть:
Смотрите, основной код программы (самая нижняя строка) состоит всего из одной строки – вызова нашей функции. Да, кстати, чтобы было понимание. Если мы пишем название функции в коде и ставим скобки – это является вызовом, т.е. интерпретатор, видя скобки, понимает, что вы хотите функцию запустить. Если скобок не будет, функция не запустится.
Имена для функций желательно давать такие, чтобы было понятно, что она делает. В нашем случае RND – это привычная аббревиатура генератора случайных чисел. Ограничения для имен функций точно такие же, как и для обычных переменных.
Давайте модифицируем код. Раньше для импорта модулей мы использовали инструкцию import. Теперь же предлагаем немного модифицировать ее:
from random import randint
Эта инструкция читается как «из модуля random импортируй метод randint». То есть, мы импортировали только один метод из множества доступных. Для чего это нужно? Для того, чтобы не нагружать программу ненужным объемом данных – потому что под все, что мы импортируем выделяется место в оперативной памяти, а значит, и замедляет быстродействие (гипотетически).
Плюс, к тому же, когда мы импортируем одну функцию или метод, нам в основном коде нет необходимости писать название модуля, как мы это делали раньше:
random.randint()
Теперь достаточно писать просто название метода:
randint()
Если есть необходимость или желание переименовать импортированную функцию или метод (например, их название слишком длинное), то инструкция импорта принимает такой вид:
from random import randint as rnd
Это читается как «из модуля random импортируй метод randint как rnd».
Теперь давайте немного усложним задачу, создав функцию superPrint(), которая будет выводить случайное число в заданном диапазоне в таком виде:
Случайное число в диапазоне между … и … : …
Обратите внимание, мы воспользовались новой инструкцией по импорту randint. Причем назвали этот метод своим именем, как нам показалось удобным – rnd.
Далее, смотрите, наша функция научилась принимать входные данные: a и b. Важно запомнить, что количество посылаемых в функцию данных и принимаемых функцией данных должно быть одинаковым. Если мы указали, что в функцию должны прийти два значения, то мы не можем послать туда одно или три значения. Будет ошибка. В дальнейшем мы еще будем говорить о том, как сделать так, чтобы можно было посылать любое количество данных. Но на данном этапе нужно научиться не ошибаться в количестве переменных.
Основной код нашей программы состоит из двух строк: строка ввода диапазона и строка вызова (запуска) функции superPrint(a, b). Тут стоит сказать, что передаваемые данные должны быть такого типа, каким его ожидает получить функция. В нашем примере функция ожидает два целых числа, поэтому мы и посылаем два целых числа superPrint(int(a), int(b)).
В программировании есть понятие глобальной и локальной переменных и области их видимости. Глобальная переменная работает и сохраняет свои значения во всем коде программы, в том числе и в функциях. А локальная переменная создается и работает только в функции или основном коде программы. В нашем примере переменные a и b в строке объявления функции superPrint(a, b) являются локальными. То есть они будут работать только внутри этой функции, их значения будут известны только этой функции. А переменные a и b в строке ввода данных из основной части программы – это уже совсем другие переменные, со своими значениями. Не нужно их путать. В данном случае было просто удобно их одинаково назвать, чтобы показать, как данные посылаются в функцию и как принимаются функцией. На самом деле, неважно, как переменные были бы названы. Одинаково бы сработала программа, например, если бы мы создавали функцию с другими переменными superPrint(x, y). Соответственно, на x и y нужно было бы заменить все a и b внутри функции:
Как создавать глобальные переменные, значения которых можно будет использовать внутри функций, мы будем изучать далее. На данном этапе это не требуется.
До настоящего времени мы создавали функции, которые просто что-то делают: получают значения, обрабатывают их и самостоятельно выводят на экран результат своих действий. А если это не требуется? Если нужно, чтобы функция производила какие-то действия, и посылала обратно результат этих действий в основной код программы? Чтобы потом, уже в основном коде с результатом предпринимать какие-то действия: выводить, или дальше работать; возможно, что посылать результат в другую функцию для дальнейшей обработки. Как это сделать?
Возврат данных (например, результата) из функции в основной код осуществляется посредством команды return. Кстати, это общепринятая команда для многих языков программирования.
В качестве примера давайте создадим функцию, которая будет создавать список из случайных N целых чисел заданного диапазона. Результат (полученный список) функция будет отправлять обратно в основной код. Вот как это выглядит:
Прокомментируем.
Функцию назвали listRND – потому что ее задача состоит в том, чтобы создать список случайных чисел. На вход функция получает три переменных, отсылает один массив. Еще раз напоминаем, что массив с название arr в функции и массив с названием arr в основном коде – это совершенно разные массивы, друг на друга не влияющие. Просто нам показалось это удобным – одинаково их назвать. Путаницы быть не должно из-за маленького размера и простоты программы.
Как читается третья строка основного кода программы:
arr = listRND(int(a), int(b), n)
Здесь мы говорим: создаем список из того, что нам даст функция. Иными словами, значение переменной arr является результатом выполнения функции listRND().
Итак, главное, что нужно запомнить:
- Функции могут возвращать какие-то данные, результат их работы, либо же ничего не возвращать. Если функция возвращает результат, то, по сути, она является переменной, хранящей в себе этот результат. Поэтому ее (функцию) можно присвоить другой переменной – как в нашем примере.
- Функция может получать данные или не получать. Если получает, то количество и тип посылаемых в функцию данных должно равняться количеству принимаемых функцией данных.
- Название функциям желательно придумывать, исходя из их назначения – чтобы было понятно, что они делают. Тогда, если код программы большой, и используется множество разных функций, будет понятнее, что за что отвечает.
Комменты приветствуются, за палец вверх - отдельное спасибо. Удачи!
------------------------------
Список уроков Программирование на Python для начинающих. Базовый уровень
------------------------------
Задания
1. Создать функцию для получения списка букв из заданного слова.
2. Используя функцию из предыдущего задания создать программу, которая получает три слова и создает из них новое, в котором буквы выстроены по принципу: сначала первые буквы всех слов, потом вторые буквы и т.д.
3. Даны три файла с названиями «1.txt», «2.txt» и «3.txt». Написать программу, которая создаст четвертый файл и запишет в него последовательно содержимое трех исходных файлов, причем содержимое каждого должно быть в отдельных абзацах и перед каждым из абзацев должен стоять номер файла. Для упрощения работы с файлами создать функцию получения содержимого файла.
4. Произвести рефакторинг игры «Угадай число». Для этого разделить код программы на логические части и перенести их в функции, оставив в основном коде только логику взаимодействия между функциями. Функции прокомментировать – чтобы было понятно, что за что отвечает.
5. Вывести все простые числа от M до N включительно.
2 <= M <= N <= 300
Вывести числа в порядке возрастания через пробел. Если между M и N включительно нет простых - вывести "Absent". В функцию вынести определение простого числа. Создать пять попыток со случайными числами M и N, удовлетворяющими условию. Для этого создать отдельную функцию. Сначала выводить на экран M и N, потом результат.