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