# Вызываем функцию с аргументом say_hello (my_name)
В результате выполнения этого программного кода получаем следующий результат (жирным шрифтом выделено введенное пользователем значение):
Результат:
Добрый день!
Как Вас зовут? Алексей Васильев
Здравствуйте, Алексей Васильев!
Код достаточно простой, но мы его все же прокомментируем. В программе объявляется две функции. Функция уоur_nаmе( ) не имеет аргументов. При выполнении этой функции сначала командой print ("Добрый день!") отображается приветствие. Затем пользователю предлагается вести свое имя. Введенное пользователем текстовое значение запоминается в переменной name. Вся команда выглядит как name=input ("Как Вас зовут?") .
После этого с помощью инструкции return name значение переменной name возвращается в качестве результата функции your_narne( ). Таким образом, у этой функции нет аргументов, но зато она возвращает результат. И ее результат – это то, что вводит пользователь (предполагается, что имя пользователя).
Еще одна функция say_hello( ) нужна для отображения приветствия.
У функции один аргумент (обозначен как txt). Текст сообщения, которое отображается при вызове функции, формируется с учетом значения аргумента txt, переданного функции. Результат функция не возвращает. В теле функции всего одна команда print (" Здравствуйте, " , txt + " ! "), которой в консольное окно выводится сообщение.
Описанные функции используем следующим образом. Сначала командой my_narne=your_name ( ) вызываем функцию your _ name ( ) и результат вызова записываем в переменную my_narne. Затем командой say_hello(my_name) вызываем функцию say_hello( ), передав ей аргументом переменную my_ name. Результат этих действий таков, как показано выше.
Для аргументов функций нередко задают значения по умолчанию. То есть для аргументов функции допускается указать. значение, которое будет использовано, если аргумент функции явно неуказан. Можно и иначе: если при вызове функции аргумент не указан, то вместо него используется значение по умолчанию.
Чтобы задать значение аргумента по умолчанию, в описании функции после имени этого аргумента через знак равенства указывается значение по умолчанию. У функции, как мы знаем, возможно наличие нескольких
20
аргументов. Часть этих аргументов может иметь значения по умолчанию, а остальные - нет. Важно помнить, что в описании функции при перечислении аргументов сначала указываются аргументы без значений по умолчанию, а аргументы со значениями по умолчанию размещаются в конце.
Примеры функций со значениями аргументов по умолчанию приведены в программном коде листинге:
#1 -я функция с одним аргументом.
#У аргумента есть значение по умолчанию
def print_text ( txt=" Знaчeниe аргумента по умолчанию . "): print ( txt )
#2 -я функция с двумя аргументами.
#У второго аргумента есть значение по умолчанию
def show_args (a, b="Bтopoй аргумент не указан. " ) :
print (a, b)
#3 - я функция с двумя аргументами.
#У аргументов есть значения по умолчанию
def my_func (x=" l -й аргумент х. " , у= " 2 -й аргумент у . " , ) :
print (x, y)
#Проверяем работу 1 -й функции .
#Функции передан один аргумент print_text ( "Apгyмeнт указан явно ." )
#Функции аргументы не передаются print_text ( )
#Проверяем работу 2-й функции .
#Функции переданы два аргумента
show_args ("Пepвый аргумент ." , "Второй аргумент ." )
#Функции передан один аргумент show_args ( "Пepвый аргумент . " )
#Проверяем работу 3 -й функции .
#Функции аргументы не передаются my_func ( )
#Функции передан один аргумент my_func ( "Oдин из аргументов ." )
#Функции передан один аргумент .
#Переданный аргумент идентифицирован явно my_func (y="Oдин из аргументов .")
В результате выполнения программного кода получаем следующий результат:
21
Аргумент указан явно.
Значение аргумента по умолчанию. Первый аргумент. Второй аргумент.
Первый аргумент. Второй аргумент не указан. 1 -й аргумент х. 2 -й аргумент у.
Один из аргументов. 2 -й аргумент у. 1 -й аргумент х. Один из аргументов.
Мы объявляем три функции. Все три функции действуют по одной схеме: значения аргументов выводятся на экран. Мы подразумеваем, что все три функции оперируют с текстовыми аргументами. Некоторые из этих аргументов имеют значения по умолчанию. Так, у функции print_text() один аргумент, и у этого аргумента есть значение по умолчанию. Мы вызываем эту функцию без аргумента (в этом случае используется значение аргумента по умолчанию), а также вызываем эту функцию с одним аргументом (в этом случае используется переданное аргументом значение).
Уфункции show_args() два аргумента, и у второго аргумента есть значение по умолчанию. Поэтому если вызвать функцию с одним аргументом, то для второго аргумента используется значение по умолчанию. Если передаются два аргумента, то для обоих аргументов используются те значения, что переданы.
Уфункции my_func(), как и в предыдущем случае, два аргумента, но теперь у обоих аргументов есть значения по умолчанию. Если мы вызовем эту функцию с двумя аргументами, то интриги не будет – те значения, что переданы аргументами, будут использованы при выполнении кода функции. Если функции при вызове передан один аргумент, то возникает вопрос: какой это аргумент – первый или второй? Ведь значение по умолчанию есть и у первого, и у второго аргумента. Поэтому теоретически переданное функции значение может быть, как первым, так и вторым аргументом.
По умолчанию считается, что функции передается первый аргумент, а для второго используется значение по умолчанию. Но у нас есть еще одна возможность: мы можем явно указать, для какого аргумента явно указано значение. В этом случае при вызове функции указывается не только значение аргумента, но и его имя (то, которое указывалось при описании функции). Используется формат имя_ аргумента=значение.
Примером может быть команда my_func(у="Один из аргументов."). В этом случае для первого аргумента используется значение по умолчанию, а переданное функции значение – это значение второго аргумента.
Таким образом, передача аргументов при вызове функции возможна:
– без указания имени аргументов, при этом значения аргументов передаются строго в той последовательности, как эти аргументы были описаны
вфункции (такой способ передачи аргументов называют позиционным);
22
– с явным указанием имени аргументов, при этом порядок перечисления аргументов не имеет значения (такой способ называется пере дачей аргументов по ключу или по имени, а сами аргументы иногда называют именованными).
Если при вызове функции часть аргументов передается по ключу, а часть
– позиционным способом, то в команде вызова сначала указываются позиционные аргументы, а затем те, что передаются по ключу. Стоит также особо обратить внимание, что способ описания аргументов (при определении функции) не зависит tого, как предполагается передавать аргументы при вызове функции (по ключу или позиционно).
Предположим, нам нужно описать функцию такую, чтобы ее можно было вызывать с разным количеством аргументов. Здесь важно, что количество аргументов не ограничено – мы наперед не знаем, сколько в принципе будет передаваться аргументов функции. В этом случае мы описываем функцию с одним аргументом, но перед этим аргументом ставим звездочку *. Такой аргумент отождествляется со списком, элементы которого формируются реальными аргументами, что переданы функции при вызове. Другими словами, наш "звездный" аргумент в теле функции обрабатывается как спи сок. Но при вызове функции аргументы передаются, как обычно. Например, функция может быть описана так:
def get_sum(*nums): s=0
for a in nums: s+=a
return s
Данная функция в качестве результата будет возвращать сумму чисел, переданных аргументами функции. Скажем, значением выражения get_sum (1, 3, 5, 2) будет число 11, а значение выражения get_sum (- 2, 4) - Число 2.
При описании функций иногда удобно использовать рекурсию. Рекурсия подразумевает, что в программном коде функции используется вызов этой же самой функции (но обычно с другим аргументом). Лучше всего сказанное проиллюстрировать на примере. В листинге ниже приведен программный код функции, которой по порядковому номеру вычисляется число из последовательности Фибоначчи. При описании функции использована рекурсия.
#Функция для вычислений чисел Фибоначчи.
#При описании функции использована рекурсия def Fib (n):
#Первое и второе число
#в последовательности равны 1
23
if n==l or n==2: return 1
# Числа в последовательности равно сумме двух предыдущих else:
return Fib (n- l) +Fib (n - 2)
#Проверяем работу функции print ("Чиcлa Фибоначчи: ")
#Вычисляем 1 5 первых чисел Фибоначчи for i in range ( l , 1 6 ) :
print (Fib ( i ) , end=" " )
Врезультате выполнения программы в ряд через пробел отображается 15 чисел из последовательности Фибоначчи:
Числа Фибоначчи:
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610
Функция для вычисления чисел Фибоначчи в нашем исполнении называется Fib() и у нее один аргумент (обозначен как n) – это порядковый номер числа в последовательности . По этому номеру необходимо вычислить число. Процесс вычислений мы реализуем с помощью условного оператора, в котором проверяем значение аргумента функции. Точнее, проверяется условие n==l or n==2. Условие истинно, если аргумент n равен 1 или 2, то есть если речь идет о первом или втором числе в последовательности. В этом случае число Фибоначчи равно 1. Поэтому если условие истинно, выполняется инструкция return 1. То есть если функции Fib() значение аргумента равно 1 или 2, функцией возвращается значение 1.
Пока все просто. Ситуация усложняется, если условие n==l o r n==2 ложно. Ложно условие, если индекс у числа (его порядковый номер в последовательности) больше чем 2 (экзотические варианты с отрицательными и нецелыми индексами мы не рассматриваем). И здесь мы вспоминаем правило вычисления чисел в последовательности Фибоначчи: каждое число (кроме первых двух) – это сумма двух предыдущих. Далее, если число Фибоначчи с порядковым номером n возвращается в результате вызова функции командой Fib(n), то два предыдущих числа - это Fib(n-1) и Fib(n- 2). Поэтому в теле функции (с аргументом n) в условном операторе в еlsе -блоке выполняется команда return Fib(n-1) + F ib (n - 2). Собственно, на этом все. У нас есть программный код функции, и этот программный код рабочий.
Для проверки работы функции Fib () мы с ее помощью вычисляем и выводим в одну строку 15 первых чисел из последовательности Фибоначчи.
Хотя рекурсия и делает обычно программные коды компактными и интуитивно понятными, метод рекурсивного определения функции нельзя назвать экономным в плане использования системных ресурсов. Вместе с тем, нередко рекурсия является единственно возможным на практике способом реализации программного кода функции.
Рассмотрим еще один пример рекурсии. На этот раз перепишем пример из листинга, в котором, напомним, представлена программа для решения
24