Python аргументы функций. Функции

Последнее обновление: 11.04.2018

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

Def имя_функции ([параметры]): инструкции

Определение функции начинается с выражения def , которое состоит из имени функции, набора скобок с параметрами и двоеточия. Параметры в скобках необязательны. А со следующей строки идет блок инструкций, которые выполняет функция. Все инструкции функции имеют отступы от начала строки.

Например, определение простейшей функции:

Def say_hello(): print("Hello")

Функция называется say_hello . Она не имеет параметров и содержит одну единственную инструкцию, которая выводит на консоль строку "Hello".

Для вызова функции указывается имя функции, после которого в скобках идет передача значений для всех ее параметров. Например:

Def say_hello(): print("Hello") say_hello() say_hello() say_hello()

Здесь три раза подряд вызывается функция say_hello. В итоге мы получим следующий консольный вывод:

Hello Hello Hello

Теперь определим и используем функцию с параметрами:

Def say_hello(name): print("Hello,",name) say_hello("Tom") say_hello("Bob") say_hello("Alice")

Функция принимает параметр name, и при вызове функции мы можем передать вместо параметра какой-либо значение:

Hello, Tom Hello, Bob Hello, Alice

Значения по умолчанию

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

Def say_hello(name="Tom"): print("Hello,", name) say_hello() say_hello("Bob")

Здесь параметр name является необязательным. И если мы не передаем при вызове функции для него значение, то применяется значение по умолчанию, то есть строка "Tom".

Именованные параметры

При передаче значений функция сопоставляет их с параметрами в том порядке, в котором они передаются. Например, пусть есть следующая функция:

Def display_info(name, age): print("Name:", name, "\t", "Age:", age) display_info("Tom", 22)

При вызове функции первое значение "Tom" передается первому параметру - параметру name, второе значение - число 22 передается второму параметру - age. И так далее по порядку. Использование именованных параметров позволяет переопределить порядок передачи:

Def display_info(name, age): print("Name:", name, "\t", "Age:", age) display_info(age=22, name="Tom")

Именованные параметры предполагают указание имени параметра с присвоением ему значения при вызове функции.

Неопределенное количество параметров

С помощью символа звездочки можно определить неопределенное количество параметров:

Def sum(*params): result = 0 for n in params: result += n return result sumOfNumbers1 = sum(1, 2, 3, 4, 5) # 15 sumOfNumbers2 = sum(3, 4, 5, 6) # 18 print(sumOfNumbers1) print(sumOfNumbers2)

В данном случае функция sum принимает один параметр - *params , но звездочка перед названием параметра указывает, что фактически на место этого параметра мы можем передать неопределенное количество значений или набор значений. В самой функции с помощью цикла for можно пройтись по этому набору и произвести с переданными значениями различные действия. Например, в данном случае возвращается сумма чисел.

Возвращение результата

Функция может возвращать результат. Для этого в функции используется оператор return , после которого указывается возвращаемое значение:

Def exchange(usd_rate, money): result = round(money/usd_rate, 2) return result result1 = exchange(60, 30000) print(result1) result2 = exchange(56, 30000) print(result2) result3 = exchange(65, 30000) print(result3)

Поскольку функция возвращает значение, то мы можем присвоить это значение какой-либо переменной и затем использовать ее: result2 = exchange(56, 30000) .

В Python функция может возвращать сразу несколько значений:

Def create_default_user(): name = "Tom" age = 33 return name, age user_name, user_age = create_default_user() print("Name:", user_name, "\t Age:", user_age)

Здесь функция create_default_user возвращает два значения: name и age. При вызове функции эти значения по порядку присваиваются переменным user_name и user_age, и мы их можем использовать.

Функция main

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

Def main(): say_hello("Tom") usd_rate = 56 money = 30000 result = exchange(usd_rate, money) print("К выдаче", result, "долларов") def say_hello(name): print("Hello,", name) def exchange(usd_rate, money): result = round(money/usd_rate, 2) return result # Вызов функции main main()

Функции могут передавать какие-либо данные из своих тел в основную ветку программы. Говорят, что функция возвращает значение. В большинстве языков программирования, в том числе Python, выход из функции и передача данных в то место, откуда она была вызвана, выполняется оператором return.

Если интерпретатор Питона, выполняя тело функции, встречает return, то он "забирает" значение, указанное после этой команды, и "уходит" из функции.

def cylinder() : r = float (input () ) h = float (input () ) # площадь боковой поверхности цилиндра: side = 2 * 3.14 * r * h # площадь одного основания цилиндра: circle = 3.14 * r**2 # полная площадь цилиндра: full = side + 2 * circle return full square = cylinder() print (square)

Пример выполнения:

3 7 188.4

В данной программе в основную ветку из функции возвращается значение локальной переменной full . Не сама переменная, а ее значение, в данном случае – какое-либо число, полученное в результате вычисления площади цилиндра.

В основной ветке программы это значение присваивается глобальной переменной square . То есть выражение square = cylinder() выполняется так:

    Вызывается функция cylinder() .

    Из нее возвращается значение.

    Это значение присваивается переменной square .

Не обязательно присваивать результат переменной, его можно сразу вывести на экран:

Print (cylinder() )

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

В функции может быть несколько операторов return. Однако всегда выполняется только один из них. Тот, которого первым достигнет поток выполнения. Допустим, мы решили обработать исключение, возникающее на некорректный ввод. Пусть тогда в ветке except обработчика исключений происходит выход из функции без всяких вычислений и передачи значения:

def cylinder() : try : r = float (input () ) h = float (input () ) except ValueError : return side = 2 * 3.14 * r * h circle = 3.14 * r**2 full = side + 2 * circle return full print (cylinder() )

Если попытаться вместо цифр ввести буквы, то сработает return, вложенный в except. Он завершит выполнение функции, так что все нижеследующие вычисления, в том числе return full, будут опущены. Пример выполнения:

Но постойте! Что это за слово None, которое нам вернул "пустой" return? Это ничего, такой объект – "ничто". Он принадлежит классу NoneType. До этого мы знали четыре типа данных, они же четыре класса: int, float, str, bool. Пришло время пятого.

Когда после return ничего не указывается, то по умолчанию считается, что там стоит объект None. Но никто вам не мешает явно написать return None.

Более того. Ранее мы рассматривали функции, которые вроде бы не возвращали никакого значения, потому что в них не было оператора return. На самом деле возвращали, просто мы не обращали на него внимание, не присваивали никакой переменной и не выводили на экран. В Python всякая функция что-либо возвращает. Если в ней нет оператора return, то она возвращает None. То же самое, как если в ней имеется "пустой" return.

Возврат нескольких значений

В Питоне позволительно возвращать из функции несколько объектов, перечислив их через запятую после команды return:

def cylinder() : r = float (input () ) h = float (input () ) side = 2 * 3.14 * r * h circle = 3.14 * r**2 full = side + 2 * circle return side, full sCyl, fCyl = cylinder() print ("Площадь боковой поверхности %.2f" % sCyl) print ("Полная площадь %.2f" % fCyl)

Из функции cylinder() возвращаются два значения. Первое из них присваивается переменной sCyl , второе – fCyl . Возможность такого группового присвоения – особенность Python, обычно не характерная для других языков:

>>> a, b, c = 10 , 15 , 19 >>> a 10 >>> b 15 >>> c 19

Фокус здесь в том, что перечисление значений через запятую (например, 10, 15, 19) создает объект типа tuple. На русский переводится как "кортеж". Это разновидность структур данных, которые будут изучены позже.

Когда же кортеж присваивается сразу нескольким переменным, то происходит сопоставление его элементов соответствующим в очереди переменным. Это называется распаковкой.

Таким образом, когда из функции возвращается несколько значений, на самом деле из нее возвращается один объект класса tuple. Перед возвратом эти несколько значений упаковываются в кортеж. Если же после оператора return стоит только одна переменная или объект, то ее/его тип сохраняется как есть.

Распаковка не является обязательной. Будет работать и так:

… print (cylinder() )

Пример выполнения:

4 3 (75.36 , 175.84 )

На экран выводится кортеж, о чем говорят круглые скобки. Его также можно присвоить одной переменной, а потом вывести ее значение на экран.

Быстрая навигация:
1.31 Списки - массивы. Первое знакомство. 1.30 Функции которые возвращают результат - return 1.29 Подпрограммы: функции и процедуры в Питоне 1.28 Преобразование типов данных - int() 1.27 Ввод данных с клавиатуры - input() 1.26 Типы и размеры данных 1.25 Цикл с предусловием - while. Числа Фибоначчи 1.24 Измерение длины строки, списки 1.23 Срезы строк - вывод определенного количества символов из имеющегося текста 1.22 Строки и управляющие символы 1.21 Системные ошибки в процессе отладки программы 1.20 Оператор ветвления - if, комментарии 1.19 Вывод на печать - print(), быстрый ввод данных, округление, комментарии 1.18 Типы программирования. Часть 2. Объектно-ориентированное программирование 1.17 Типы программирования. Часть 1. Структурное программирование. Циклы 1.16 Представление символьной информации - ASCII 1.15 Деление двоичных чисел 1.14 Математические операции с двоичными числами 1.13 Как хранится и записывается информация. Биты и байты 1.12 Перевод целых чисел десятичной системы счисления в другую систему 1.11 Перевод целых чисел из шестнадцатеричной системы счисления в десятичную 1.10 Перевод целого двоичного числа в шестнадцатеричное 1.9 Перевод целого двоичного числа в другую систему счисления 1.8 Системы счисления 1.7 Булевая алгебра. Логические выражения 1.6 Базовые понятия. Часть 3 - Числа, выражения, операнды, знаки операций 1.5 Базовые понятия. Часть 2 - Программа, данные 1.4 Базовые понятия. Часть 1 - Задача и алгоритм 1.3 Среда разработки СИ 1.2 История языков программирования 1.1 Введение

При написании программ в любом языке программирования необходимо стремиться к написанию компактных кодов, чтобы можно было легко ориентироваться в самом коде.
Бывает что реализовать таким образом свой код не представляется возможным и, зачастую, программный код выглядит как нескончаемой длинны свиток древнего документа, который занимает 10 - 15 экранов монитора по вертикали...
Конечно же разобраться в такой программе бывает крайне сложно самому автору такого творения.

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

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

Как это выглядит на практике?

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

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

В разных языках программирования такие подпрограммы называются:

Процедурами или
- функциями

В языке СИ такие подпрограммы называются функциями.

Кстати мы с вами уже применяли функции на практике!
Например мы с вами использовали ВСТРОЕННЫЕ в интерпретатор функции:

Print() - для вывода данных на печать неких параметров, которые были заключены в круглые скобки
- str() - для преобразования данных к строковому типу. Именно ее предварительно запускает функция print()
- int() - для преобразования данных к целому числу
- float() - для преобразования целых чисел в дробный тип
- round() - для округления некоего значения
и т.п.


Итак.
Для вызова функции достаточно набрать ее имя и в скобках перечислить требуемые параметры (аргументы) которые мы хотим передать в данную функцию.

Но было бы совсем неинтересно, если бы у нас не было возможности создавать свои собственные функции для выполнения тех или иных задач.
Что касается Питона, то в нем существует специальный оператор определения функции, имеющий следующий синтаксис:

def ИМЯ_ФУНКЦИИ(СПИСОК_ПАРАМЕТРОВ):
ПОСЛЕДОВАТЕЛЬНОСТЬ_ВЫРАЖЕНИЙ

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

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

Возвращаясь к расчету чисел Фибоначчи рассмотрим на его примере работу вызова функции.
Мы возьмем еще один вариант расчета чисел Фибоначчи, который не рассматривали ранее.
Он основан на параллельном присваивании значений переменным.

Def fib(n): a, b = 0, 1 while a < n: print(a, end = " ") a, b = b, a + b print()

Если вкратце, то строка:
a, b = 0, 1
означает запись (но не полностью эквивалентна ей):
a = 0 b = 1

А строка
a, b = b, a + b
означает запись:
a = b b = a + b

Рассмотрим код по строкам:

1
def fib(n):
- определить (def ) функцию по имени fib с параметрами (аргументами) указанными в круглых скобках которые мы хотим передать в эту самую функцию по имени fib .
Т.е. в качестве параметра n мы будем передавать значение для которого будет производиться расчет. Это число будет передаваться в нашу функцию в качестве аргумента.

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

2
a, b = 0, 1
Инициализируем переменные соответствующими значениями:
a = 0 b = 1

3
while a < n:
Оператор цикла while - будет выполняться до тех пор, пока будет выполнено условие цикла a
Здесь также после двоеточия открывается новый блок имеющий НЕПОСРЕДСТВЕННОЕ отношение только к циклу.
Этот блок будет печататься после перевода строки с дополнительным отступом.

4
print(a, end = " ")
Выводим на печать данные переменной а и пробел после каждого витка цикла

5
a, b = b, a + b
Присваиваем переменным соответствующие значения:
a = b b = a + b
Для изменения исходных данных и продолжения работы расчета чисел Фибоначчи

6
print()

Обратите внимание на то, что данный print() нужно печатать ПОД while ... т.е. он уже относится не к телу цикла while , а к телу функции fib
Однако для чего нам нужен второй print() да еще и с пустыми скобками?

В данном случае это вывод пустой строки - сделать "отбивку" - перенос строки. А еще вернее, данная функция выводит на печать символ перевода строки.
В нашем случае можно и не использовать.

Итак мы определили функцию fib для расчета чисел Фибоначчи и она, как вы заметили - не работает.

Для того, чтобы она заработала необходимо ее ВЫЗВАТЬ и передать ей некий параметр для расчетов.
Вызываем нашу функцию и передаем в качестве аргумента значение 40 .
В результате мы должны получить расчет чисел Фибоначчи для всех чисел до 40 :

Печатаем в интерпретаторе Python:
fib(40)
Получаем:

0 1 1 2 3 5 8 13 21 34

Вы можете еще раз вызвать функцию fib() с другим параметром и точно также получите вывод необходимых данных.
Например введем
fib(400)
И получим:

0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

Таким образом нашу функцию можно запускать необходимое количество раз.

Во многих языках программирования процедура и функция не синонимы и имеют отличия друг от друга.
Чем же они отличаются друг от друга в таких языках программирования?

Функция - возвращает значение
- Процедура - не возвращает значение

Поясним на примере:


Если мы можем использовать такую запись (только в качестве примера):
x = fib(n) - то это функция, она присваивает полученное значение переменной x (в данном случае переменной x ничего записано не будет)

Если же возможна только запись fib(n) - то это процедура.

Таким образом мы можем сказать, что наш пример является ПРОЦЕДУРОЙ.

Как в Питоне использовать наш код для расчета чисел Фибоначчи в качестве функции мы рассмотрим несколько позже...

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

Функции можно сравнить с небольшими программками, которые сами по себе, т. е. автономно, не исполняются, а встраиваются в обычную программу. Нередко их так и называют – подпрограммы. Других ключевых отличий функций от программ нет. Функции также при необходимости могут получать и возвращать данные. Только обычно они их получают не с ввода (клавиатуры, файла и др.), а из вызывающей программы. Сюда же они возвращают результат своей работы.

Существует множество встроенных в язык программирования функций. С некоторыми такими в 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, "шт." )

Пример исполнения программы:

Сколько бананов и ананасов для обезьян? 15 5 Всего 20 шт. Сколько жуков и червей для ежей? 50 12 Всего 62 шт. Сколько рыб и моллюсков для выдр? 16 8 Всего 24 шт.

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

Определение функции. Оператор def

В языке программирования Python функции определяются с помощью оператора def. Рассмотрим код:

def countFood() : a = int (input () ) b = int (input () ) print ("Всего" , a+b, "шт." )

Это пример определения функции. Как и другие сложные инструкции вроде условного оператора и циклов функция состоит из заголовка и тела. Заголовок оканчивается двоеточием и переходом на новую строку. Тело имеет отступ.

Ключевое слово def сообщает интерпретатору, что перед ним определение функции. За def следует имя функции. Оно может быть любым, также как и всякий идентификатор, например, переменная. В программировании весьма желательно давать всему осмысленные имена. Так в данном случае функция названа "посчитатьЕду" в переводе на русский.

После имени функции ставятся скобки. В приведенном примере они пустые. Это значит, что функция не принимает никакие данные из вызывающей ее программы. Однако она могла бы их принимать, и тогда в скобках были бы указаны так называемые параметры.

После двоеточия следует тело, содержащее инструкции, которые выполняются при вызове функции. Следует различать определение функции и ее вызов. В программном коде они не рядом и не вместе. Можно определить функцию, но ни разу ее не вызвать. Нельзя вызвать функцию, которая не была определена. Определив функцию, но ни разу не вызвав ее, вы никогда не выполните ее тела.

Вызов функции

Рассмотрим полную версию программы с функцией:

def countFood() : a = int (input () ) b = int (input () ) print ("Всего" , a+b, "шт." ) print ("Сколько бананов и ананасов для обезьян?" ) countFood() print ("Сколько жуков и червей для ежей?" ) countFood() print ("Сколько рыб и моллюсков для выдр?" ) countFood()

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

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

В языке Python определение функции должно предшествовать ее вызовам. Это связано с тем, что интерпретатор читает код строка за строкой и о том, что находится ниже по течению, ему еще неизвестно. Поэтому если вызов функции предшествует ее определению, то возникает ошибка (выбрасывается исключение NameError):

print ("Сколько бананов и ананасов для обезьян?" ) countFood() print ("Сколько жуков и червей для ежей?" ) countFood() print ("Сколько рыб и моллюсков для выдр?" ) countFood() def countFood() : a = int (input () ) b = int (input () ) print ("Всего" , a+b, "шт." )

Результат:

Сколько бананов и ананасов для обезьян? Traceback (most recent call last ) : File "test.py" , line 2 , in < module> countFood() NameError: name "countFood" is not defined

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

Функции придают программе структуру

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

Пусть надо написать программу, вычисляющую площади разных фигур. Пользователь указывает, площадь какой фигуры он хочет вычислить. После этого вводит исходные данные. Например, длину и ширину в случае прямоугольника. Чтобы разделить поток выполнения на несколько ветвей, следует использовать оператор if-elif-else:

figure = input () 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(), ее тело содержит выражение вывода на экран слова "Отрицательное".

Именные функции, инструкция def

Функция в python - объект, принимающий аргументы и возвращающий значение. Обычно функция определяется с помощью инструкции def.

Определим простейшую функцию:

Инструкция return говорит, что нужно вернуть значение. В нашем случае функция возвращает сумму x и y.

Теперь мы ее можем вызвать:

>>> add(1, 10)

>>> add("abc", "def")

Функция может быть любой сложности и возвращать любые объекты (списки, кортежи, и даже функции!):

>>> def newfunc(n):

Def myfunc(x):

Return x + n

Return myfunc

>>> new = newfunc(100) # new - это функция

>>> new(200)

Функция может и не заканчиваться инструкцией return, при этом функция вернет значениеNone:

>>> def func():

>>> print(func())

Аргументы функции

Функция может принимать произвольное количество аргументов или не принимать их вовсе. Также распространены функции с произвольным числом аргументов, функции с позиционными и именованными аргументами, обязательными и необязательными.

>>> def func(a, b, c=2): # c - необязательный аргумент

Return a + b + c

>>> func(1, 2) # a = 1, b = 2, c = 2 (по умолчанию)

>>> func(1, 2, 3) # a = 1, b = 2, c = 3

>>> func(a=1, b=3) # a = 1, b = 3, c = 2

>>> func(a=3, c=6) # a = 3, c = 6, b не определен

Traceback (most recent call last):

File "", line 1, in

TypeError: func() takes at least 2 arguments (2 given)

Функция также может принимать переменное количество позиционных аргументов, тогда перед именем ставится *:

>>> def func(*args):

>>> func(1, 2, 3, "abc")

(1, 2, 3, "abc")

>>> func(1)

Как видно из примера, args - это кортежиз всех переданных аргументов функции, и с переменной можно работать также, как и с кортежем.

Функция может принимать и произвольное число именованных аргументов, тогда перед именем ставится **:

>>> def func(**kwargs):

Return kwargs

>>> func(a=1, b=2, c=3)

{"a": 1, "c": 3, "b": 2}

>>> func(a="python")

В переменной kwargs у нас хранится словарь, с которым мы, опять-таки, можем делать все, что нам заблагорассудится.

Анонимные функции, инструкция lambda

Анонимные функции могут содержать лишь одно выражение, но и выполняются они быстрее. Анонимные функции создаются с помощью инструкции lambda. Кроме этого, их не обязательно присваивать переменной, как делали мы инструкцией def func():

>>> func = lambda x, y: x + y

>>> func(1, 2)

>>> func("a", "b")

>>> (lambda x, y: x + y)(1, 2)

>>> (lambda x, y: x + y)("a", "b")

lambda функции, в отличие от обычной, не требуется инструкция return, а в остальном, ведет себя точно так же:

>>> func = lambda *args: args

>>> func(1, 2, 3, 4)

19. Понятие рекурсии, реализация в языке Python

В программировании рекурсия - вызов функции (процедуры) из неё же самой, непосредственно (простая рекурсия) или через другие функции (сложная или косвенная рекурсия), например, функция вызывает функцию, а функция- функцию. Количество вложенных вызовов функции или процедуры называется глубиной рекурсии.

Проще сказать нельзя. Про рекурсии есть известная поговорка:

Чтобы понять рекурсию, нужно сперва понять рекурсию

Итак, питон позволяет работать с рекурсиями легко и непринужденно. Самый первый пример рекурсии, с которой сталкиваются большинство программистов - это нахождение факториала. Код может быть таким:

def factorial(n):

if n <= 1: return 1

else: return n * factorial(n - 1)

Как видно, мы записали инструкцию if else слегка необычным для питона способом, но это позволяется в данном случаее, ввиду того, что читабельность здесь не ухудшается, но не следует злоупотреблять таким стилем. И вообще, PEP8всех рассудит. :)

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

    Существует ограничение на глубину рекурсии. По умолчанию оно равно 1000.

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

    Не смотря на это - существует ограничение размером стека, который устанавливается операционной системой.

    Рекурсия в Python не может использоваться в функциях-генераторах и сопрограммах. Однако, можно это поведение исправить, но лучше не стоит.

    И последнее - применение декораторов к рекурсивным функциям может приводить к неожиданным результатам, поэтому будьте очень осторожны декорируя рекурсивные функции.

Также, всегда следует определять точки выхода из рекурсивных функций. Это как с циклами - бесконечный цикл может здорово «просадить» вашу операционную систему. И наконец, где лучше применять рекурсию, а где лучше воздержаться и обойтись, например циклами. Конечно, здесь многое зависит от задачи, но всегда следует помнить, что рекурсия в разы медленнее цикла. Так уж устроен питон, что вызов функции дорого вам обходится:) Вообще, в циклах не стоит вызывать функции, а уж рекурсивные функции и подавно.

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



Просмотров