В процессе нашего обучения мы изучили ряд встроенных в Python функций: print()
, input()
, max()
, min()
и др. Часто в программах требуется использовать какую-то часть кода несколько раз. В таком случае программисты создают функции. Функции помогают использовать написанный код в программах многократно, а также делают его более понятным за счёт деления на блоки.
Синтаксис создания функции выглядит следующим образом:
1def <имя функции>(<аргументы функции>):
2 <тело функции>
Правила для записи имени функции такие же, как и для переменных: имя может содержать строчные буквы английского алфавита, цифры и знаки подчёркивания. Аргументы функции — это её параметры, которые становятся переменными в теле функции. Тело функции содержит код, который работает с аргументами и внешними переменными, а затем возвращает результат с помощью оператора return
. При возврате значения функция прекращает свою работу, а интерпретатор продолжает работу программы, подставив на место вызова функции возвращённое значение.
Напишем функцию, которая проверяет, что список целых чисел, передаваемый ей как аргумент, содержит только чётные числа:
1def only_even(numbers):
2 result = True
3 for x in numbers:
4 if x % 2 != 0:
5 result = False
6 break
7 return result
8
9
10print(only_even([2, 4, 6]))
11print(only_even([1, 2, 3]))
Вывод программы:
True False
В функциях можно использовать несколько операторов return
. Первый сработавший в теле функции оператор return
остановит выполнение функции и вернёт её значение. Наш пример можно упростить, использовав вместо флага result несколько точек возврата значения:
1def only_even(numbers):
2 for x in numbers:
3 if x % 2 != 0:
4 return False
5 return True
6
7
8print(only_even([2, 4, 6]))
9print(only_even([1, 2, 3]))
Вывод программы:
True False
Обратите внимание: функция в Python всегда возвращает результат, даже если в ней нет return
или присутствует return
без возвращаемого значения. Тогда возвращаемый результат будет None
— специальный тип данных в Python, который дословно можно перевести с английского как «ничего». Например, None
возвращает функция print()
:
1print(print("Эту строку выведет функция до возврата значения."))
Вывод программы:
Эту строку выведет функция до возврата значения. None
Из функции можно вернуть сразу несколько значений. Для этого их нужно перечислить через запятую после оператора return
. В программу эти значения вернутся в кортеже. Добавим в нашу функцию дополнительно возврат индекса первого нечётного элемента, который встретится:
1def only_even(numbers):
2 for i, x in enumerate(numbers):
3 if x % 2 != 0:
4 return False, i
5 return True
6
7
8print(only_even([2, 4, 6]))
9print(only_even([1, 2, 3]))
Вывод программы:
True (False, 0)
Обратите внимание, что в одном случае мы возвращаем значение логического типа, в другом — кортеж. Тогда в программе нужно будет дополнительно проверять, значение какого типа вернёт функция, так как от этого зависит набор операций и методов, доступных для этого типа данных.
Итак, функции могут работать с аргументами и возвращать значения. Значение аргумента доступно только внутри функции. Покажем это на примере:
1def only_even(numbers):
2 for i, x in enumerate(numbers):
3 if x % 2 != 0:
4 return False, i
5 return True
6
7
8print(numbers)
Вывод программы:
NameError: name 'numbers' is not defined
Таким образом, аргумент функции недоступен вне этой функции. Это произошло, поскольку аргумент функции является локальной переменной. Он существует только во время выполнения функции и доступен только внутри неё. Также говорят, что аргумент функции находится в локальной области видимости функции.
Кроме локальной существует глобальная область видимости. Переменные, созданные вне функций, то есть в основном коде программы, находятся в глобальной области видимости. Это означает, что к ним можно получить доступ в любой части программы. В следующем примере в функции используется строка password
из глобальной области видимости:
1def check_password(pwd):
2 return pwd == password
3
4
5password = "Python"
6print(check_password("123"))
Вывод программы:
False
Возможность изменения значения переменной из глобальной области видимости зависит от того, к какому типу данных переменная относится — к изменяемому или неизменяемому. Например, если она является списком, то после применения к нему изменяющих его операций и методов список изменит своё значение:
1def list_modify():
2 del sample[-1]
3
4
5sample = [1, 2, 3]
6list_modify()
7print(sample)
Вывод программы:
[1, 2]
Если же попытаться записать новое значение во внешнюю переменную (неважно, изменяемого или неизменяемого типа), то внутри функции будет создана локальная переменная с тем же именем, что и у внешней:
1def list_modify():
2 sample = [4, 5, 6]
3
4
5sample = [1, 2, 3]
6list_modify()
7print(sample)
Вывод программы:
[1, 2, 3]
Мы уже знаем, что аргумент функции — это локальная переменная. К нему также относится правило: изменение значения переменной (если это разрешено типом данных) действует на внешнюю переменную, а присваивание нового значения создаёт локальную переменную функции:
1def list_modify_1(list_arg):
2 # создаём новый локальный список, не имеющий связи с внешним
3 list_arg = [1, 2, 3, 4]
4
5
6def list_modify_2(list_arg):
7 # меняем исходный внешний список, переданный как аргумент
8 list_arg += [4]
9
10
11sample_1 = [1, 2, 3]
12sample_2 = [1, 2, 3]
13list_modify_1(sample_1)
14list_modify_2(sample_2)
15print(sample_1)
16print(sample_2)
Вывод программы:
[1, 2, 3] [1, 2, 3, 4]
Если в функции необходимо менять значения переменных из глобальной области видимости путём операции присваивания, то нужно в теле функции сделать эти переменные глобальными с помощью ключевого слова global
. Тогда в функции не будут создаваться локальные переменные с такими же именами, а значение поменяется в глобальной переменной:
1def inc():
2 global x
3 x += 1
4 print(f"Количество вызовов функции равно {x}.")
5
6
7x = 0
8inc()
9inc()
10inc()
Вывод программы:
Количество вызовов функции равно 1. Количество вызовов функции равно 2. Количество вызовов функции равно 3.
Однако использование глобальных переменных будет приводить к усложнению анализа программы, так как изменить своё значение глобальная переменная может практически в любой части программы. Поэтому использовать глобальные переменные можно только в случае, если это действительно необходимо и написать программу без них сложнее или невозможно. Нашу программу можно написать и без глобальных переменных, для этого достаточно передавать в функцию значение, полученное с предыдущего вызова функции.
1def f(count):
2 count += 1
3 print(f'Количество вызовов функции равно {count}.')
4 return count
5
6
7count_f = 0
8count_f = f(count_f)
9count_f = f(count_f)
10count_f = f(count_f)
Вывод программы:
Количество вызовов функции равно 1. Количество вызовов функции равно 2. Количество вызовов функции равно 3.