Как работает функция def в Python?
The keyword def introduces a function definition. It must be followed by the function name and the parenthesized list of formal parameters. The statements that form the body of the function start at the next line, and must be indented.
def say_hello(message): print(message)
Функции в программировании
Функция в программировании представляет собой обособленный участок кода, который можно вызывать, обратившись к нему по имени, которым он был назван. При вызове происходит выполнение команд тела функции.
Функции можно сравнить с небольшими программками, которые сами по себе, то есть автономно, не исполняются, а встраиваются в обычную программу. Нередко их так и называют – подпрограммы. Других ключевых отличий функций от программ нет. Функции также при необходимости могут получать и возвращать данные. Только обычно они их получают не с ввода (клавиатуры, файла и др.), а из вызывающей программы. Сюда же они возвращают результат своей работы.
Существует множество встроенных в язык программирования функций. С некоторыми такими в Python мы уже сталкивались. Это print() , input() , int() , float() , str() , type() . Код их тела нам не виден, он где-то «спрятан внутри языка». Нам же предоставляется только интерфейс – имя функции.
С другой стороны, программист всегда может определять свои функции. Их называют пользовательскими. В данном случае под «пользователем» понимают программиста, а не того, кто пользует программу. Разберемся, зачем нам эти функции, и как их создавать.
Предположим, надо три раза подряд запрашивать на ввод пару чисел и складывать их. С этой целью можно использовать цикл:
i = 0 while i 3: a = int(input()) b = int(input()) print(a + b) i += 1
Однако, что если перед каждым запросом чисел, надо выводить надпись, зачем они нужны, и каждый раз эта надпись разная. Мы не можем прервать цикл, а затем вернуться к тому же циклу обратно. Придется отказаться от него, и тогда получится длинный код, содержащий в разных местах одинаковые участки:
print("Сколько бананов и ананасов для обезьян?") a = int(input()) b = int(input()) print("Всего", a + b, "шт.") print("Сколько жуков и червей для ежей?") a = int(input()) b = int(input()) print("Всего", a + b, "шт.") print("Сколько рыб и моллюсков для выдр?") a = int(input()) b = int(input()) print("Всего", a + b, "шт.")
Пример исполнения программы:
Сколько бананов и ананасов для обезьян? 15 5 Всего 20 шт. Сколько жуков и червей для ежей? 50 12 Всего 62 шт. Сколько рыб и моллюсков для выдр? 16 8 Всего 24 шт.
Внедрение функций позволяет решить проблему дублирования кода в разных местах программы. Благодаря им можно исполнять один и тот же участок кода не сразу, а только тогда, когда он понадобится.
Определение функции. Оператор def
В языке программирования Python функции определяются с помощью оператора def . Рассмотрим код:
def count_food(): a = int(input()) b = int(input()) print("Всего", a + b, "шт.")
Это пример определения функции. Как и другие сложные инструкции вроде условного оператора и циклов функция состоит из заголовка и тела. Заголовок оканчивается двоеточием и переходом на новую строку. Тело имеет отступ.
Ключевое слово def сообщает интерпретатору, что перед ним определение функции. За def следует имя функции. Оно может быть любым, также как и всякий идентификатор, например, переменная. В программировании весьма желательно давать всему осмысленные имена. Так в данном случае функция названа «посчитать_еду» в переводе на русский.
После имени функции ставятся скобки. В приведенном примере они пустые. Это значит, что функция не принимает никакие данные из вызывающей ее программы. Однако она могла бы их принимать, и тогда в скобках были бы указаны так называемые параметры.
После двоеточия следует тело, содержащее инструкции, которые выполняются при вызове функции. Следует различать определение функции и ее вызов. В программном коде они не рядом и не вместе. Можно определить функцию, но ни разу ее не вызвать. Нельзя вызвать функцию, которая не была определена. Определив функцию, но ни разу не вызвав ее, вы никогда не выполните ее тела.
Вызов функции
Рассмотрим полную версию программы с функцией:
def count_food(): a = int(input()) b = int(input()) print("Всего", a+b, "шт.") print("Сколько бананов и ананасов для обезьян?") count_food() print("Сколько жуков и червей для ежей?") count_food() print("Сколько рыб и моллюсков для выдр?") count_food()
После вывода на экран каждого информационного сообщения осуществляется вызов функции, который выглядит просто как упоминание ее имени со скобками. Поскольку в функцию мы ничего не передаем скобки опять же пустые. В приведенном коде функция вызывается три раза.
Когда функция вызывается, поток выполнения программы переходит к ее определению и начинает исполнять ее тело. После того, как тело функции исполнено, поток выполнения возвращается в основной код в то место, где функция вызывалась. Далее исполняется следующее за вызовом выражение.
В языке Python определение функции должно предшествовать ее вызовам. Это связано с тем, что интерпретатор читает код строка за строкой и о том, что находится ниже по течению, ему еще неизвестно. Поэтому если вызов функции предшествует ее определению, то возникает ошибка (выбрасывается исключение NameError ):
print("Сколько бананов и ананасов для обезьян?") count_food() print("Сколько жуков и червей для ежей?") count_food() print("Сколько рыб и моллюсков для выдр?") count_food() def count_food(): a = int(input()) b = int(input()) print("Всего", a + b, "шт.")
Сколько бананов и ананасов для обезьян? Traceback (most recent call last): File "test.py", line 2, in count_food() NameError: name 'count_food' is not defined
Для многих компилируемых языков это не обязательное условие. Там можно определять и вызывать функцию в произвольных местах программы. Однако для удобочитаемости кода программисты даже в этом случае предпочитают соблюдать определенные правила.
Функции придают программе структуру
Польза функций не только в возможности многократного вызова одного и того же кода из разных мест программы. Не менее важно, что благодаря им программа обретает истинную структуру. Функции как бы разделяют ее на обособленные части, каждая из которых выполняет свою конкретную задачу.
Пусть надо написать программу, вычисляющую площади разных фигур. Пользователь указывает, площадь какой фигуры он хочет вычислить. После этого вводит исходные данные. Например, длину и ширину в случае прямоугольника. Чтобы разделить поток выполнения на несколько ветвей, следует использовать оператор if-elif-else:
figure = input("1-прямоугольник, 2-треугольник, 3-круг: ") if figure == '1': a = float(input("Ширина: ")) b = float(input("Высота: ")) print("Площадь: %.2f" % (a * b)) elif figure == '2': a = float(input("Основание: ")) h = float(input("Высота: ")) print("Площадь: %.2f" % (0.5 * a * h)) elif figure == '3': r = float(input("Радиус: ")) print("Площадь: %.2f" % (3.14 * r ** 2)) else: print("Ошибка ввода")
Здесь нет никаких функций, и все прекрасно. Но напишем вариант с функциями:
def rectangle(): a = float(input("Ширина: ")) b = float(input("Высота: ")) print("Площадь: %.2f" % (a * b)) def triangle(): a = float(input("Основание: ")) h = float(input("Высота: ")) print("Площадь: %.2f" % (0.5 * a * h)) def circle(): r = float(input("Радиус: ")) print("Площадь: %.2f" % (3.14 * r ** 2)) figure = input("1-прямоугольник, 2-треугольник, 3-круг: ") if figure == '1': rectangle() elif figure == '2': triangle() elif figure == '3': circle() else: print("Ошибка ввода")
Он кажется сложнее, а каждая из трех функций вызывается всего один раз. Однако из общей логики программы как бы убраны и обособлены инструкции для нахождения площадей. Программа теперь состоит из отдельных «кирпичиков Лего». В основной ветке мы можем комбинировать их как угодно. Она играет роль управляющего механизма.
Если нам когда-нибудь захочется вычислять площадь треугольника по формуле Герона, а не через высоту, то не придется искать код во всей программе (представьте, что она состоит из тысяч строк кода как реальные программы). Мы пойдем к месту определения функций и изменим тело одной из них.
Если понадобиться использовать эти функции в какой-нибудь другой программе, то мы сможем импортировать их туда, сославшись на данный файл с кодом (как это делается в Python, будет рассмотрено позже).
Практическая работа
В программировании можно из одной функции вызывать другую. Для иллюстрации этой возможности напишите программу по следующему описанию.
Основная ветка программы, не считая заголовков функций, состоит из одной строки кода. Это вызов функции test() . В ней запрашивается на ввод целое число. Если оно положительное, то вызывается функция positive() , тело которой содержит команду вывода на экран слова «Положительное». Если число отрицательное, то вызывается функция negative() , ее тело содержит выражение вывода на экран слова «Отрицательное».
Понятно, что вызов test() должен следовать после определения функций. Однако имеет ли значение порядок определения самих функций? То есть должны ли определения positive() и negative() предшествовать test() или могут следовать после него? Проверьте вашу гипотезу, поменяв объявления функций местами. Попробуйте объяснить результат.
Примеры решения и дополнительные уроки в pdf-версии курса
X Скрыть Наверх
Python. Введение в программирование
Основы Python — кратко. Часть 5. Определение функций, основы.
Начав писать главу про ООП, понял что совсем забыл освятить такой большой и нужный раздел Пайтона как функции. Тема это большая и обширная, потому, чтобы не сильно растягивать паузу между уроками, решил разделить ее на 2 части. Сначала расскажу основы, потом уже углубленные особенности Пайтоновского функциестроения.
Функции в Пайтоне объявляются не просто, а очень просто. Вот пример самой простой:
def empty_func(): pass
Начинается объявление с ключевого слова def, что как не сложно догадаться является сокращением от define. После него идет имя функции. После имени в круглых скобках задается список параметров, в данном случае отсутствующих.
Тело функции пишется с отступом со следующей строки. учтите, что в Пайтоне функции с пустым телом запрещены, потому в качестве тела приведенной выше функции используется «пустой оператор» pass.
Теперь рассмотрим пример посерьезнее.
def safe_div(x, y): """Do a safe division :-) for fun and profit""" if y != 0: z = x / y print z return z else: print "Yippie-kay-yay, motherf___er!"
В этом примере есть несколько нововведений. первое, что бросается в глаза — это строка документации (docstring), идущая сразу после тела функции.
Обычно эта строка занимает не одну строку исходного текста (простите за каламбур) и потому задается в тройных кавычках. Она предназначена для описания функции, ее предназначения, параметров и т.п. Все хорошие ИДЕ умеют с этой строкой работать. Получить к ней доступ можно и из самой программы, используя свойство __doc__:
print safe_div.__doc__
Этим свойством (да, да, именно свойством, в Пайтоне даже функции на самом деле — классы) удобно пользоваться во время сеансов работы интерактивной консоли.
>>> from ftplib import FTP >>> print FTP.__doc__ An FTP client class. To create a connection, call the class using these argument: host, user, passwd, acct These are all strings, and have default value ''. Then use self.connect() with optional host and port argument. # дальнейшее почикано мною :-)
Вернемся к нашей исходной функции. Суть ее очень проста, она принимает 2 параметра: х и у. Если у не равен 0, она делит х на у, выводит результат на экран и возвращает свое частное в виде результата. Результат функции возвращают с помощью команды return. Благодаря механизму кортежей, описанному в прошлом уроке, функции в Пайтоне могут возвращать одновременно множество объектов.
Если же делитель все-таки равен нулю, функция выводит сообщение об ошибке. Неверно было бы предположить что в этом случае функция ничего не вернет. Правильнее будет сказать что функция вернет «ничего» 🙂 Иначе говоря, если в функции отсутствует оператор return, или же он вызван без параметров, то функция возвращает специальное значение None. В этом легко убедиться вызвав что-то типа print safe_div(10, 0).
Вот пример слегка посложнее, он взят из доклада-презентации Гвидо ван Россума.
def gcd(a, b): "Нахождение НОД" while a != 0: a,b = b%a,a # параллельное определение return b
Данная функция находит наибольший общий делитель двух чисел.
В общем, следует учитывать, что параметры в функции Пайтоном передаются по ссылке. Еще одним, возможно нетривиальным фактом к которому придется привыкать — является тот факт что сами функции являются значением, которое можно присваивать. Если воспользоваться нашей функцией safe_div для дальнейших экспериментов, то можно написать следующий код.
mystic_function = safe_div print mystic_function(10, 4)
Вот на этот раз и все, «за бортом» осталось еще много аспектов определения функций в Пайтоне, которые будут освещены в следующий раз.
Упражнения для проверки.
1. На основе существующей функции нахождения НОД, напишите функцию поиска НОК двух чисел.
2. Напишите подпрограмму табулирования функции, переданной в качестве аргумента. Так же аргументами задается начальное, конечное значение и шаг табуляции.
PS кстати, каков оптимальный объем «урока»? Что лучше — реже выходящие большие главы, или «лучше меньше да чаще».
Просто про функции и их аргументы в Python
Функции существуют в большинстве современных языков программирования. В императивных языках (к которым относится и Python) функция — это набор инструкций, объединенных для выполнения одной задачи. Блоки кода, однажды оформленные в виде функций, можно использовать в коде многократно. Поэтому разработчики охотно применяют этот подход на практике, чтобы облегчить работу себе и своему приложению.
Курс Англійської.
Подолай мовний бар’єр та розширюй коло друзів на розмовних клубах.
Редакция highload.today разобралась, как это работает, как создавать функции Python, на какие разновидности они делятся, как вызывать функции и передавать в них аргументы. Теперь мы готовы помочь разобраться в этом вам. И… да, примеры кода обязательно будут.

1. Что такое функция в Python
В предыдущем абзаце уже шла речь о том, что функции Python делятся на разновидности. Мы рассмотрим две классификации:
-
встроенные / не встроенные (пользовательские);
Курс Англійської.
Онлайн-навчання англійської за методикою Кембриджу — вибір понад мільярда людей.
Отличия между ними сводятся не только к синтаксису и способу использования. Не менее важно, что работают они тоже по-разному (далее мы в этом убедимся).
Встроенные функции Python выполняют очень широкий круг мелких, но важных задач. Например:
| Встроенная функция Python | Краткое описание |
| len() | вычисляет длину (количество элементов) последовательности (например, списка) |
| next() | возвращает следующий по порядку элемент последовательности (например, списка) |
| reversed() | меняет порядок элементов последовательности на обратный |
В языке Python десятки таких функций, и внутренняя реализация многих из них очень сложна. Но об этом за вас уже позаботились разработчики языка, поэтому пользуйтесь с удовольствием — как говорится, бесплатно и без регистрации. Разобраться во всех тонкостях языка Python можно на специальных курсах от наших партнеров в Powercode и ШАГ.
Пользовательские функции разработчики приложений на Python должны создавать самостоятельно. Для этого в языке существуют специальные конструкции, которыми нужно просто научиться пользоваться. И чем лучше вы этому научитесь, тем лучше будет выглядеть ваш код. И более того, его будет проще поддерживать и дорабатывать. Пользовательские функции помогают:
- разделить объемный код на понятные, осмысленные части;
- вынести повторяющийся код в один блок;
- оптимизировать скорость работы приложения.
Про встроенные функции Python в этой статье мы говорить практически не будем, но знайте, что они есть. И перед тем, как писать свою функцию, проверьте, существует ли встроенная функция, которая подходит для решения вашей задачи.
Курс Англійської.
Навчання для різних цілей та рівнів: робоча англійська, початковий рівень, курси для дітей та підлітків.
2. Именные функции (инструкция def)
Из названия термина ясно, что синтаксис такой функции обязательно должен включать ее имя:
def function_name(parameters): """здесь можно описать, что делает функция""" statement(s) return result
Первая строка — заголовок функции. Далее следуют опциональная строковая переменная (в тройных кавычках) и тело функции (обозначено как statement(s) ).
У синтаксиса функции есть ряд особенностей:
-
Заголовок функции должен начинаться с ключевого слова def .
Курс QA Manual.
Успішна кар’єра в IT-сфері без необхідності глибоких знань програмування. Очікуйте заробітню плату в розмірі 600$ після завершення навчання.
Функции Python могут иметь произвольное имя. Но желательно, чтобы имя было глаголом и отражало суть задачи, которую решает эта функция.
Пример:
def greet(name): """ Функция выводит приветственное сообщение для имени name """ print("Hello, " + name + ". Good morning!")
Напомним также общие правила именования переменных, которые полностью распространяются и на имена функций:
- Имя может состоять из чисел, латинских символов и символа нижнего подчеркивания и не должно включать что-либо другое.
- Имя функции не должно включать пробелы.
- В начале имени нельзя ставить цифру.
- X и x — это два разных идентификатора (регистр имеет значение).
- Имена функций рекомендуют начинать со строчной буквы.
- В качестве имени пользовательской функции запрещено использовать ключевые слова языка Python и имена его встроенных функций.
Вызов функции
Функцию можно вызвать из консоли Python, из скрипта или из другой функции. Чтобы сделать это для именной функции мы должны написать ее имя, а в скобках при необходимости передать ей параметры, либо оставить скобки пустыми.
>>> say_goodbye('Paul') Goodbye, Paul.
вызов функции из консоли Python
def say_goodbye(name): print("Goodbye, " + name) say_goodbye('Paul')
вызов функции say_goodbye из скрипта Python и вызов функции print из функции say_goodbye
ВАЖНО: язык Python не позволяет вызывать функцию до того, как она была создана. Потому что анализатор Python в данном случае сканирует код сверху вниз и не может найти объявление функции, которая была вызвана.
# вызов функции say_goodbye('Paul') # реализация функции def say_goodbye(name): print("Goodbye, " + name) # Ошибка: в точке say_goodbye('Paul') функция 'say_goodbye' не определена, не существует
вызов функции до ее объявления
Без вызова именная функция никогда не запустится. То есть, мы обязательно должны вызвать именную функцию, чтобы заставить работать код внутри нее, включая инструкцию return , о которой расскажем в специальном разделе.

3. Документирование функции
После заголовка функции идет опциональная строка, в которой можно написать любой текст. Но в данном случае она нужна для описания, документирования работы функции. Ее еще называют иностранным словосочетанием docstring . Вряд ли вы помните, что делает и как работает каждая функция, которую вы написали. Если даже вы это помните, то остальные разработчики, которые будут сопровождать или как-то еще использовать ваш код, не в курсе.
Поэтому такое документирование позволяет в итоге сэкономить время. А те минуты, которые вы потратите на него, окупятся с избытком.
Вспомним функцию из предыдущего примера и добавим в нее docstring :
def greet(name): """ Функция выводит приветственное сообщение для имени name """ print("Hello, " + name + ". Good morning!")
объявление функции с документированием
Все, теперь, встретившись с таким кодом, другие разработчики сразу поймут, что к чему. Понятно, что тут очень простой пример, но представьте, что это большой и запутанный код.
Но оказывается, можно сделать жизнь разработчиков еще проще. Встретив функцию, они могут не искать ее объявление по всему проекту, а воспользоваться специальным атрибутом __doc__ .
>>> print(greet.__doc__) Функция выводит приветственное сообщение для имени name
вывод значения атрибута __doc__ для функции greet
4. Аргументы функции
Вновь вернемся к заголовку функции и разберемся, какими могут быть эти самые параметры, они же — аргументы. Сколько их может быть? В предельном случае их может не быть вовсе. Тогда получаем такой заголовок:
def function_name():
и вот такой вызов функции:
function_name();
Рассмотрим теперь более распространенный случай, когда аргументов несколько.
def say_goodbye(name, msg): print("Goodbye", name + ', ' + msg) say_goodbye("Monica", "Sweet dreams!")
Функция say_goodbye принимает два аргумента — переменные name и msg . Вызывая функцию, мы передаем в нее значения, которые соответствуют аргументам. То есть эти значения (“ Monica ” и “ Sweet dreams! “) подставляются вместо переменных name и msg соответственно.
Результат работы программы:
Goodbye Monica, Sweet dreams!
Отлично. Два аргумента — два переданных значения. Все работает.
Но что будет, если мы передадим в эту же функцию только одно значение или совсем не передадим значения?
>>> say_goodbye("Monica") TypeError: say_goodbye() missing 1 required positional argument: 'msg' >>> say_goodbye() TypeError: say_goodbye() missing 2 required positional arguments: 'name' and 'msg'
Как видите программа работать не будет и выдаст ошибку для каждого вызова. Получается, Python не позволяет передавать количество значений, не совпадающее с количеством аргументов, указанных в объявлении функции?
Если отвечать в очень грубом приближении, то не позволяет. Но далее мы увидим, как можно решить эту задачу, если очень хочется.
Значения аргументов по умолчанию
Python позволяет задавать значения аргументов по умолчанию.
def say_goodbye(name, msg="Sweet dreams!"): print("Goodbye", name + ', ' + msg)
Конструкция msg=»Sweet dreams!» в первой строке означает, что при вызове функции значение аргумента msg можно не задавать. Достаточно задать только значение аргумента name , а значение msg подставится само.
И тогда программа будет работать без ошибок:
Goodbye Monica, Sweet dreams!
При этом вариант вызова с полным количеством аргументов также будет работать
say_goodbye(«Bruce», «See you!»)
и программа выдаст
Goodbye Bruce, See you!
В данном случае значение, которое мы передали в качестве второго аргумента, будет использовано вместо значения по умолчанию, заданное в заголовке функции.
Однако, в силу особенностей языка Python, мы не можем переписать код так:
def say_goodbye(msg = «Sweet dreams!», name):
Потому что получим ошибку.
SyntaxError: non-default argument follows default argument
Это означает, что справа от аргумента со значением по умолчанию могут располагаться только такие же аргументы, имеющие значение по умолчанию. Обычные аргументы без значений по умолчанию должны находиться слева.
Порядок передачи аргументов
При вызове функции нельзя просто так поменять местами значения, которые вы передаете в качестве аргументов.
say_goodbye(«See you!», «Bruce»)
приведет к следующему результату:
Goodbye See you!, Bruce
Потому что в объявлении функции аргументы расположены не в том порядке:
def say_goodbye(name, msg):
В Python такие аргументы называются позиционными. Но существуют и аргументы другого типа — именованные или ключевые (калька с английского keyword arguments ). Если точнее, то существует другой способ передачи значений аргументов при вызове функции.
# 2 ключевые аргументы say_goodbye(name = "Bruce", msg = "See you!") # 2 ключевые аргументы в другом порядке say_goodbye(msg = "See you!",name = "Bruce")
Такая конструкция позволяет игнорировать порядок передачи аргументов при вызове функции. Хотя можно использовать и смешанный вариант:
# позиционный и ключевой аргумент say_goodbye("Bruce", msg = "See you!")
Функции с неизвестным количеством аргументов
Если мы не знаем, сколько значений будет обрабатывать функция, можно задать ее аргументы в виде списка.
def say_goodbye(*names): """Функция выведет приветствие для каждого имени из полученного names""" for name in names: print("Goodbye", name)
В этом случае перед именем списка пишется знак * . Тут names — это список имен неизвестной длины. Функция обрабатывает его, как обычный список.
Вызывая эту функцию, мы можем в качестве аргументов передавать произвольное количество значений. Они преобразуются в список и полученный список автоматически подставляется вместо переменной names.
say_goodbye(«Monica», «Luke», «Steve», «John»)
Результат работы программы:
Goodbye Monica Goodbye Luke Goodbye Steve Goodbye John
5. Инструкция return
Несмотря на то, что эта инструкция опциональная, она помогает в двух случаях:
- Когда нужно вернуть результат работы функции в виде значения, которое может использовано вне функции — например, записано во внешнюю переменную.
def sum(a,b): return a+b
- Когда нужно прервать работу функции и вернуться к той точке программы, из которой была вызвана эта функция.
def division(a,d): if d == 0: # если делитель равен нулю return "Нельзя делить на ноль" # мы прерываем работу функции return a / d
Посмотрим, как будут работать эти функции с различными значениями аргументов.
print(sum(2, 4)) print(sum(2, -4))
6 -2 print(division(4, 2)) print(division(4, 0))
2.0 Нельзя делить на ноль
Если в коде функции нет инструкции return , она не возвращает ничего. Запустив в консоли функцию из предыдущего раздела, в третьей строке мы получим None .
>>> print(say_goodbye("May")) Goodbye, May. None
6. Глобальные и локальные переменные
В этой статье мы еще не встречали функции, в которых помимо аргументов использованы переменные. Например:
def multiplicator(x): k = 2 return k * x
Что это за переменная k ?
Чтобы ответить на этот вопрос, нужно ввести понятия области видимости и времени жизни переменных. Область видимости переменной — это фрагмент программы (блок), внутри которого эта переменная существует и доступна. О такой переменной говорят, что она видна в данной области видимости (простите за тавтологию).
В приведенном выше примере переменная k видна только внутри функции. В этом случае говорят, что переменная является локальной.
Время жизни переменной — это временной промежуток, в течение которого переменная хранится в памяти (и доступна хотя бы для чтения).
Локальные переменные обычно живут до тех пор, пока функция не завершит свою работу после очередного вызова. Во время каждого вызова функции все ее локальные переменные сбрасываются и инициализируются заново. Значения (если они были изменены) локальных переменных из предыдущих вызовов функция не хранит.
Хорошо, тогда что будет, если создать переменную с тем же именем, но за пределами функции?
def multiplicator(x): k = 2 print("Значение локальной переменной k:", k) return k*x k = 20 multiplicator(4) print("Значение внешней переменной k:", k)
Значение локальной переменной k: 2 Значение внешней переменной k: 20
В этом примере внешняя переменная k никак не влияет на результат работы функции. Дело в том, что сначала функция ищет переменную с подходящим именем внутри своей локальной области видимости — где как раз находится локальная переменная k .

Если мы удалим эту переменную из реализации функции, то она будет искать k уже во внешних по отношению к ней блоках кода (пошагово двигаясь изнутри наружу). В данном случае она найдет внешнюю переменную k , равную 20 и использует ее значение для своих вычислений.
Но если нам нужно не просто использовать, а еще и модифицировать это значение, необходимо внести изменения в код:
def multiplicator(x): global k k = 2 print("Значение локальной переменной k:", k) return k*x k = 20 multiplicator(4) print("Значение внешней переменной k:", k)
Добавив выделенные жирными строки ( global k и k = 2 ), мы сообщаем анализатору Python, что не намерены создавать локальную переменную k : мы просто модифицируем глобальную переменную.
Язык программирования Python – один из самых востребованных. С каждым годом потребность в специалистах с его знаниями только растет. Поэтому если вам он интересен, то вы можете записаться на курс к нашим друзьям из академии ШАГ или Mate Academy. Получите высокооплачиваемую профессию на долгие годы.
7. Рекурсивные функции
В разделе про python def function мы упоминали, что функцию можно вызывать, находясь внутри другой функции. Оказывается, функция может вызывать саму себя внутри своего же исходного кода.
def factorial(x): #условие окончания рекурсии if x == 1: return 1 else: return (x * factorial(x-1)) num = 3 print("Факториал числа", num, "равен", factorial(num))
Такие функции называют рекурсивными. В данном случае factorial(x) один раз вызывается из внешней программы и два раза — из самой себя. Перед каждым из двух этих вызовов значение аргумента x уменьшается на 1. Это происходит до тех пор, пока x не достигнет значения, равного 1. Это так называемое условие окончания рекурсии.
Программа отработает и выведет соответствующее сообщение:
Факториал числа 3 равен 6
Последовательность вычислений можно представить в хронологическом порядке:
| Операция | Значение x | Состояние программы | Условие окончания рекурсии |
| factorial(3) | 3 | первый вызов функции | не выполнено |
| 3 * factorial(2) | 2 | второй вызов, погружение в рекурсию | не выполнено |
| 3 * (2 * factorial(1)) | 1 | третий вызов, погружение в рекурсию | не выполнено |
| 3 * (2 * 1) | 1 | выход из рекурсии (всплываем) | выполнено |
| return 3 * 2 | 2 | выход из рекурсии | выполнено |
| 6 | 3 | возвращение результата | выполнено |
8. Анонимные функции (инструкция lambda)
Их также называют лямбда-функциями (это отсылка к математическому инструментарию под названием Лямбда Исчисление). Ключевое отличие анонимных от именных функций, казалось бы, заложено в их названиях. Но это не совсем так.
Во-первых, синтаксис функций отличается кардинально:
lambda аргументы: выражение
Во-вторых, лямбда-функция может выполнить только одну инструкцию (действие).
Для чего тогда нам нужны такие узкоспециализированные функции?
Анонимные функции идеально подходят, если нужно передать функцию в другую функцию в качестве аргумента. И если больше нигде переданная функция не будет вызвана — имя ей не понадобится. Ну и требование выполнять только одно действие (вычислять лишь одно выражение) здесь тоже играет в плюс, так как делает код более лаконичным.
l = [2, 5, 1, 4] l.sort(key=lambda x: x)
l = [2, 5, 1, 4] l.sort(key=lambda x: -x)
В первом примере список будет отсортирован по своим исходным (не измененным) значениям. Во втором примере лямбда-функция подставит вместо каждого элемента списка это же число, но со знаком минус. В результате список будет отсортирован в обратном порядке.
Важно также отметить, что лямбда-функции не используют инструкцию return , но всегда возвращают результат. В одном из наших примеров это результат вычисления выражения -x .
9. Присвоение функции переменной
Присвоение анонимной функции
Будет очень в тему еще один пример с анонимной функцией:
double = lambda x: x * 2
В данном случае мы просто присвоили имя этой лямбда-функции, но не вызвали ее. Этот код эквивалентен вот такой реализации именной функции:
def double(x): print(x * 2) return x * 2
Теперь для вызова нашей анонимной функции, записанной в переменную double , нужно добавить ей скобки, подставив произвольное значение аргумента. Например:
Присвоение именной функции
Хорошо, а какие чудеса мы сможем сотворить, если запишем в переменную именную функцию? Для примера создадим вот такую функцию:
def f(): print("I am f")
Зададимся целью ввести такую переменную g , чтобы
- g() запускал вызов функции f
- с печатью строки I am f
Первый способ
def f(): print("I am f") # присваивание g = f # вызов функции g()
Это работает, потому что благодаря присваиванию переменная g указывает на тот же участок памяти (блок кода), что и функция f . А значит, подставив к g скобки, мы получим обычный вызов функции.
Второй способ
Используем так называемую лямбда-обертку. Создадим лямбда-функцию без аргументов, с возвращаемым значением в виде f() и запишем ее в переменную g (примерно так мы делали в начале раздела).
def f(): print("I am f") # лямбда-обертка g = lambda : f() # вызов функции g()
Это будет работать так же, так как лямбда-функция, записанная в переменную g запустится (то есть отправит на выполнение инструкцию f() ) только после выполнения инструкции g()
Заключение
Функции Python — это достаточно гибкий механизм, но в нем легко запутаться, не зная тонкостей. Надеюсь, в этой статье нам удалось заложить основы и объяснить важные детали при работе с функциями. Но если у вас остались вопросы, или вы хотите более подробно вникнуть в язык программирования Python, то курсы наших друзей Hillel и Powercode, помогут вам освоить новые знания.
Видео: примеры использования функции map()
Курс Управління командою в бізнесі.
Онлайн-курс для ефективного управління командою, спрямований на створення проактивних та самостійних команд, де мікроменеджмент не потрібний.
