Глава 4. Функции
Функции должны делать одну вещь и делать ее хорошо и делать только ее.
Роберт С. Мартин
В этой главе вы изучите функции — составные инструкции, которые могут принимать данные ввода, выполнять указания и возвращать данные вывода.
Функции позволяют определять и повторно использовать определенную функ- циональность.
Синтаксис
С этого момента для объяснения концепций программирования я буду исполь- зовать новое соглашение (согласованный способ делать что-то). Например, для иллюстрации использования функции вывода данных я буду записывать следую- щее: print("__ ").
Здесь я объединил код Python и курсивный текст — это суть данной концеп- ции. В подобных примерах все, кроме курсивного текста внутри, является до- пустимым кодом Python. При выполнении примера курсивный текст нужно за- менить описанным кодом. Этот текст подсказывает, какой именно код нужно использовать. В данном случае, значение __ надо заменить тем текстом, который нужно вывести на экран.
Ввод x
Вывод f(x)
Функция f:
44Часть I
ФункцииВызвать функцию — значит передать ей данные ввода, необходимые для выпол- нения указаний и возвращения вывода. Каждый ввод в функцию является
пара-метром . Когда вы передаете функции параметр, это называется
передача пара- метра функции.
Функции в Python похожи на математические функции. Ниже показан при- мер, если вы не помните функции из алгебры:
1
# $
2
f(x)
= x
* 2
Левая часть инструкции сверху определяет функцию, f, принимающую один параметр, x. Правая часть — определение функции, которое использует переданный параметр (x), чтобы произвести вычисление и вернуть результат
(вывод). В этом случае значением функции является ее параметр, умноженный на два.
Как в Python, так и в алгебре, функция записывается следующим образом:
_ (
_ _ ). Чтобы вызвать функцию, после ее имени нужно указать круглые скобки и поместить внутрь параметры, отде- лив каждый из них запятой. Для математической функции f, определенной как f(x) = 2 * x
, значение f(2) равно 4, значен ие f(10) равно 20.
Определение функцийДля создания функций в Python выберите ее имя , определите параметры , укажи- те, что функция должна делать и какое значение возвращать. Ниже показан син- таксис определения функции.
1
# $ .
2
def _ ( ):
3
_ Математическая функция f(x) = x * 2 в Python будет выглядеть вот так:
Python_ex079.py1
def f(x):
2
return x
* 2
Ключевое слово def сообщает Python, что вы определяете функцию. После def вы указываете имя функции; оно
должно отвечать тем же правилам, что и имена переменных. Согласно конвенции, в имени функции нельзя использовать заглавные буквы, а слова должны быть разделены подчеркиванием , _ .
Как только вы присвоили своей функции имя, укажите после него круглые скобки. Внутри скобок должен содержаться один или несколько параметров.
После скобок ставится двоеточие, а новая строка начинается с отступа в четыре пробела (как с любой другой составной инструкцией). Любой код с от-
45
Введение в программирование ступом в четыре пробела после двоеточия является определением функции.
В этом случае определение нашей функции состоит только из одной строки: return x * 2. Ключевое слово return используется для определения значе- ния, которое функция выводит при вызове, то есть значения, которое она воз- вращает.
Чтобы вызвать функцию в Python, мы используем синтаксис
_
( _ _ ).
Ниже описан вызов функции f из предыдущего примера с параметром 2.
Python_ex080.py
1
# &
2
# X
3
f(2)
Консоль ничего не вывела. Можно сохранить вывод вашей функции в пере- менной и передать ее функции print.
Python_ex081.py
1
# &
2
# X
3
result
= f(2)
4
print(result)
>> 4
Вы можете сохранить результат, возвращаемый вашей функцией, в перемен- ной и использовать это значение в программе позднее.
Python_ex082.py
1
def f(x):
2
return x + 1 3 z
= f(4)
4
if z == 5:
5
print("z 5")
6
else:
7 print("z 5")
>> z 5
У функции может быть один параметр, несколько параметров или вообще их не быть. Чтобы опередить функцию, не требующую параметров, оставьте кру- глые скобки пустыми.
46
Часть I
Python_ex083.py
1
def f():
2
return 1 + 1 3
result = f()
4
print(result)
>> 2
Если хотите, чтобы функция принимала больше одного параметра, отделите каждый параметр в скобках запятой.
Python_ex084.py
1
def f(x, y, z):
2
return x + y + z
3
result
= f(1, 2, 3)
4
print(result)
>> 6
Наконец, функция не обязана содержать инструкцию return. Если функции нечего возвращать, она возвращает значение None.
Python_ex085.py
1
def f():
2
z
= 1 + 1 3
result
= f
()
4
print(result)
>> None
Встроенные функции
Python содержит библиотеку функций, встроенных в язык программирования.
Они называются встроенными функциями . Они выполняют всевозможные расчеты и задания и готовы к использованию без каких-либо дополнительных действий с вашей стороны. Вы уже встречали один пример встроенной функ- ции: первая программа, написанная вами, использовала функцию print, чтобы вывести строку ", !".
len
— еще одна встроенная функция. Она возвращает длину объекта – напри- мер, строки (т.е. количество символов в ней).
Python_ex086.py
1 len("V ")
>> 5
47Введение в программирование
Python_ex087.py1 len(" ")
>> 6
Встроенная функция str принимает объект и возвращает новый объект с типом данных str. Например, функцию str можно использовать для преобра- зования целого числа в строку.
Python_ex088.py1 str(100)
>> '100'
Функция int принимает объект и возвращает его в виде целого числа.
Python_ex089.py1 int("1")
>> 1
Функция oat принимает объект и возвращает число с плавающей точкой.
Python_ex090.py1 oat(100)
>> 100.0
Необходимо, чтобы параметр , который вы передаете функциям str, int или oat, мог стать строкой, целым числом или числом с плавающей точкой.
Функция str может принимать в качестве параметра большинство объектов, но функция int
принимает только строку, содержащую число, или объект в виде числа с плавающей точкой. Функция oat принимает только строку, содержа- щую число, или объект в виде целого числа.
Python_ex091.py1
int("110")
2
int(20.54)
3
oat("16.4")
4
oat(99)
>> 110
>> 20
>> 16.4
>> 99.0
48
Часть I
Если вы попытаетесь передать функции int или oat параметр, который нельзя преобразовать в целое число или число с плавающей точкой, Python сге- нерирует исключение .
Python_ex092.py
1 int(" Y")
>> ValueError: invalid literal for int() with base 10: ' Y'
input
— это встроенная функция, собирающая информацию от человека, ко- торый использует программу.
Python_ex093.py
1
age
= input("| & B :")
2
int_age
= int(age)
3
if int_age < 21:
4
print(" - !")
5
else:
6
print("$ !")
>> | & B :
Функция input принимает в качестве параметра строку и отображает ее че- ловеку, использующему программу. Затем пользователь может набрать ответ в оболочке, и его ответ можно сохранить в переменной — в нашем случае, в пере- менной age.
Затем используйте функцию int, чтобы преобразовать переменную age из строки в целое число. Функция input собирает данные от пользователя в виде str
, но чтобы сравнивать переменную с целыми числами, нужно, чтобы она была int
. Как только вы получили целое число, ваша инструкция if-else определяет, какое сообщение нужно выводить пользователю в зависимости от того, что тот ввел в оболочку. Если пользователь ввел число, меньшее 21, выводится текст -
!
. Если было введено число, большее 21
, выводится строка $ -
!
Многократное использование функций
Функции используются не только для вычисления и возвращения значений. Они могут инкапсулировать функциональность, которую вы пожелаете использовать повторно.
Python_ex094.py
1
def even_odd(x):
2
if x % 2 == 0:
3
print("even")
4
else:
5
print("odd")
49
Введение в программирование
7
even_odd(2)
8
even_odd(3)
>>
>>
Вы не определили значение, которое функция должна возвращать, но она все еще приносит пользу. Функция проверяет условие x % 2 == 0 и в выводе сообщает, четным или нечетным является параметр x.
Функции также позволяют писать меньше кода благодаря многократному ис- пользованию. Ниже приведен пример программы, написанной без функций.
Python_ex095.py
1
n
= input(" : ")
2
n
= int(n)
3
if n % 2 == 0:
4
print("n - .")
5
else:
6
print("n — .")
7
n
= input(" : ")
8
n
= int(n)
9
if n % 2 == 0:
10
print("n - .")
11
else:
12
print("n — .")
13
n
= input(" : ")
14
n
= int(n)
15
if n % 2 == 0:
16
print("n - .")
17
else:
18
print("n — .")
>> :
Программа трижды просит пользователя ввести число. Затем инструкция if-else проверяет, четное ли это число. Если оно четное, выводится сообще- ние n - ., в противном случае выводится n - .
Недостаток этой программы заключается в том, что она повторяет один и тот же код три раза. Можно сократить программу и сделать ее более удобной для чтения, поместив функциональность внутрь функции и вызвав ее трижды.
50Часть I
Python_ex096.py1
def even_odd():
2
n
= input(" : ")
3
n
= int(n)
4
if n
% 2
== 0:
5
print("n - .")
6
else:
7
print("n — .")
8
even_odd()
9
even_odd()
10
even_odd()
>> :
Функциональность этой программы аналогична предыдущей, но поскольку вы поместили ее в функцию, которую можно вызывать по мере необходимо- сти, код вашей программы стал короче и удобнее для чтения.
Обязательные и необязательные параметрыФункция может принимать параметры двух типов. Те, что
встречались вам до этого, называются
обязательными параметрами. Когда пользователь вызывает функцию, он должен передать в нее все обязательные параметры, иначе Python сгенерирует исключение.
В Python есть и другой вид параметров —
опциональные. Они позволяют тому, кто вызвал функцию, при необходимости передать в нее параметр, но он не являет- ся обязательным. Опциональные параметры определяются с помощью следующего синтаксиса :
_ (
_ = _ ). Как и обя- зательные, опциональные параметры нужно отделять запятыми. Ниже приведен пример функции, в коде которой используется опциональный параметр.
Python_ex097.py1
def f(x
=2):
2
return x
**x
3
print(f())
4
print(f(4))
>> 4
>> 256
Сначала функция вызывается без передачи параметра. Так как параметр необя- зательный, x автоматически становится 2, и функция возвращает 4.
Затем та же функция вызывается с параметром 4. Функция игнорирует зна- чение по умолчанию, x становится 4, и функция возвращает 256. Вы можете
51
Введение в программирование определить функцию, которая принимает как обязательные, так и опциональ- ные параметры, но обязательные нужно определять в первую очередь.
Python_ex098.py
1
def add_it(x, y=10):
2
return x + y
3
result
= add_it(2)
4
print(result)
>> 12
Область видимости
У переменных есть важное свойство, называемое областью видимости. Ког- да вы определяете переменную, ее область видимости указывает на то, какая часть вашей программы может находить и изменять значение переменной. Об- ласть видимости переменной зависит от того, где в программе была определе- на переменная. Если вы определили ее за пределами функции (или класса, о которых вы узнаете в части II), область видимости переменной — глобальная.
Тогда значение переменной можно найти и изменить из любой позиции про- граммы. Переменная с глобальной областью видимости называется глобаль-
ной переменной. Если вы определите переменную в пределах функции (или класса), у нее будет локальная область видимости: ваша программа сможет найти и изменить значение переменной только в функции, в пределах кото- рой она была определена. Ниже показаны переменные с глобальной областью видимости.
Python_ex099.py
1
x
= 1 2
y
= 2 3
z
= 3
Эти переменные не были определены внутри функции (или класса), следо- вательно, у них глобальная область видимости. Это значит, что вы можете нахо- дить и изменять их откуда угодно, в том числе изнутри функции.
Python_ex100.py
1
x
= 1 2
y
= 2 3
z
= 3 4
def f():
5
print(x)
6
print(y)
7
print(z)
52Часть I
8
f()
>> 1
>> 2
>> 3
Если вы определите эти же переменные внутри функции, то сможете лишь находить и изменять их внутри этой функции. Если вы попытаетесь получить к ним доступ вне функции, в которой они были определены, Python сгенерирует исключение .
Python_ex101.py1
def f():
2
x
= 1 3
y
= 2 4
z
= 3 5
print(x)
6
print(y)
7
print(z)
>> NameError: name 'x' is not de ned
Если вы определите переменные внутри функции, ваш код будет работать.
Python_ex102.py1
def f():
2
x
= 1 3
y
= 2 4
z
= 3 5
print(x)
6
print(y)
7
print(z)
8
f()
>> 1
>> 2
>> 3
Попытка
использовать за пределами функции переменную, определенную внутри этой функции, аналогична использованию переменной, которая еще не была определена, что приводит к вызову того же исключения.
53
Введение в программирование
Python_ex103.py
1
if x > 100:
2
print("x > 100")
>> NameError: name 'x' is not de ned
Вы можете изменять глобальную переменную откуда угодно, но для ее изме- нения внутри локальной области видимости требуется дополнительный шаг. Пе- ред переменной, которую вы желаете изменить, необходимо использовать клю- чевое слово global. Этот шаг нужен для того, чтобы удостовериться, что если вы определили переменную x внутри функции, вы случайно не измените зна- чение любой переменной, ранее определенной за пределами вашей функции.
Ниже приведен пример изменения глобальной переменной изнутри функции.
Python_ex104.py
1
x
= 100 2
def f():
3
global x
4
x
+= 1 5
print(x)
6
f()
>> 101
Без областей видимости вы могли бы получить доступ к каждой переменной в любой части программы, что создавало бы проблемы. Если у вас огромная про- грамма, и вы создали функцию, использующую переменную x, вы можете слу- чайно изменить значение переменной с таким же именем, ранее определенной где-то в программе. Подобные ошибки могут повлиять на поведение вашей про- граммы и привести к ошибкам или непредвиденным результатам. Чем большей становится ваша программа и чем больше она содержит переменных, тем веро- ятнее это произойдет.
Обработка исключений
Полагание на пользовательский ввод из функции input ограничивает вас в кон- троле этого ввода — он полностью определяется пользователем и может приво- дить к ошибкам. Скажем, вы написали программу, которая принимает от пользо- вателя два числа и выводит результат деления первого числа на второе.
Python_ex105.py
1 a
= input(" :")
2 b
= input(" X :")
3 a
= int(a)
4 b
= int(b)
54Часть I
5 print(a
/ b)
>> :
>> 10
>> X :
>> 5
>> 2
Программа как будто работает. Однако если пользователь введет 0 в каче
стве второго числа, вы столкнетесь с проблемой.
Python_ex106.py1
a
= input(" :")
2
b
= input(" X :")
3
a
= int(a)
4
b
= int(b)
5
print(a
/ b)
>> :
>> 10
>> X :
>> 0
>>
ZeroDivisionError: integer division or modulo by zero
Нельзя просто надеяться, что пользователь не введет 0. Способом выйти из положения может считаться
обработка исключений — она позволит вам проте-
стировать программу на возможные ошибки, «перехватить» исключения , если та- ковые возникают, и решить, что делать дальше.
Для обработки исключений используются ключевые слова try и except.
При использовании обработки исключений, когда пользователь вводит 0 в каче- стве второго числа, программа может вывести им сообщение о недопустимости ввода 0 вместо генерирования исключения.
Все исключения в Python являются объектами, так что вы можете использовать их в своих программах. Список встроенных исключений можете найти на странице в Интернете по адресу
goo.gl/A2Utav. Если вам кажется, что ваш код может сгене- рировать исключение, используйте составную инструкцию с ключевыми словами try и except, чтобы перехватить его.
Ветвь try содержит возможную ошибку. Ветвь except содержит код, который будет выполняться лишь в том случае, если в ветви try появится исключение. Ниже приведен пример использования обработки исключений, когда программа не пре- рывается при вводе 0 в качестве второго числа.
Python_ex107.py1
a
= input(" :")
2
b
= input(" X :")
55
Введение в программирование
3
a
= int(a)
4
b
= int(b)
5
try:
6
print(a
/ b)
7
except ZeroDivisionError:
8
print("b & .")
>> :
>> 10
>> X :
>> 0
>> b & .
Если пользователь вводит в качестве b что-то отличное от 0, запускается код в блоке try, а блок except ничего не делает. Если же пользо ватель вводит 0, вме- сто того, чтобы сгенерировать исключение, выполняется код в блоке except, и программа выводит текст b & .
Ваша программа также прервет работу, если пользователь введет строку, ко- торую Python не может преобразовать в целое число.
Python_ex108.py
1
a
= input(" :")
2
b
= input(" X :")
3
a
= int(a)
4
b
= int(b)
5
try:
6
print(a
/ b)
7
except ZeroDivisionError:
8
print("b & .")
>> :
>>
>> X :
>>
>>
ValueError: invalid literal for int() with base 10: ' '
Это можно исправить, переместив ту часть вашей программы, что принима- ет ввод, внутрь инструкции try и указав инструкции except искать два исклю- чения: ZeroDivisionError и ValueError. Исключение ValueError возника- ет, если вы передаете встроенным функциям int, string, или oat неверный ввод. С помощью круглых скобок и запятой между исключениями мы заставляем инструкцию except перехватывать два исключения.
56
Часть I
Python_ex109.py
1
try:
2 a
= input(" :")
3 b
= input(" X :")
4 a
= int(a)
5 b
= int(b)
6 print(a
/ b)
7
except(ZeroDivisionError, ValueError):
8 print("* .")
>> :
>>
>> X :
>>
>> * .
Не используйте в инструкции except переменные, определенные в ин- струкции try, поскольку исключение может возникнуть прежде, чем будет определена переменная, и как только вы попытаетесь использовать инструк- цию except, внутри нее сгенерируется исключение.
Python_ex110.py
1
try:
2 10
/ 0 3
c
= "Q W."
4
except ZeroDivisionError:
5
print(c)
>> NameError: name 'c' is not de ned
Строки документации
Когда вы определяете функцию с параметрами, иногда для ее работы необходи- мо, чтобы эти параметры были определенного типа данных. Как сообщить об этом всем, кто вызывает вашу функцию? Когда пишете функцию, вверху не поме- шает оставить комментарий, называемый строкой документации , чтобы объяс- нить, какой тип данных должен иметь каждый параметр. Строки документации объясняют, что делает функция, и какие она требует параметры.
Python_ex111.py
1
def add(x, y):
2
"""
3
B X x + y.
4
: x: Y .
57Введение в программирование
5
: y: Y .
6
:return: Y x y.
7
"""
8
return x
+ y
Первая строка
кода строки документации четко объясняет, что делает функ- ция, чтобы когда другие разработчики будут использовать вашу функцию или метод, им не приходилось читать весь ваш код в поисках ее предназначения.
Остальные строки определяют параметры функции, типы параметров, и что данная функция возвращает. Это поможет вам программировать быстрее, ведь теперь, чтобы выяснить, что делает функция, достаточно прочесть лишь строки документации, а не читать весь код.
Чтобы примеры в этой книге оставались краткими, я опустил строки доку- ментации, которые обычно использую. Когда я пишу код, то включаю строки до- кументации, делая код удобным для всех будущих читателей.
Используйте переменные, только когда это необходимоСохраняйте данные в переменной, только если собираетесь затем ее использо- вать. К примеру, не сохраняйте в переменной целое число, чтобы просто выве- сти его.
Python_ex112.py1
x
= 100 2
print(x)
>> 100
Вместо этого передавайте число сразу в функцию вывода.
Python_ex113.py1
print(100)
>> 100
Во многих примерах в этой книге я нарушаю данное правило, чтобы вам было проще понимать, что я делаю. Вам необязательно делать то же самое со своим кодом.
Словарь терминовВстроенная функция: функция, поставляющаяся с Python.
Вызов: передача функции вводных данных, необходимые для выполнения ука- заний и возвращения вывода.
Глобальная область видимости: область видимости переменной, которую мож- но найти и изменить откуда угодно в программе.
Глобальная переменная: переменная с глобальной областью видимости.
58Часть I
Локальная область видимости: область видимости переменной, которую мож- но найти и изменить только из функции (или класса), внутри которой перемен- ная была определена.
Область видимости: то, где переменную можно найти и изменить.
Обработка исключений: концепция программирования, позволяющая вам те- стировать программу на возможные ошибки, «перехватывать» исключения, если таковые возникают, и решать, что делать дальше.
Обязательный параметр: необходимый параметр.
Опциональный параметр: необязательный параметр.
Параметр: данные, переданные в функцию.
Соглашение: согласованный способ делать что-то.
Строка документации: объясняет, что делает функция, и какие она требует па- раметры.
Функции: составные инструкции, которые могут принимать данные ввода, вы- полнять указания и возвращать данные вывода.
Практикум1. Напишите функцию, которая принимает число в качестве ввода, возводит его в квадрат и возвращает.
2. Создайте функцию, которая принимает строку в качестве параметра и воз- вращает ее.
3. Напишите функцию, которая принимает три обязательных и два необяза- тельных параметра.
4. Напишите программу с двумя функциями. Первая функция должна при- нимать в качестве параметра целое число и возвращать результат деления этого числа на 2. Вторая функция должна принимать в качестве параметра целое число и возвращать результат умножения этого числа на 4. Вызовите первую функцию, сохраните результат в переменной и передайте ее в каче- стве параметра во вторую функцию.
5. Напишите функцию, которая преобразовывает строку в тип данных oat и возвращает результат. Используйте обработку исключений, чтобы перехва- тить возможные исключения.
6. Добавьте строку документации ко всем функциям, которые вы написали в за- даниях 1–5.
Решения:
chap4_challenge1.py — chap4_challenge6.py.