4.1. Функции. Области видимости. Передача параметров в функции

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

Что вы узнаете

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

Вы узнаете, как устроены локальные и глобальные переменные — и почему с глобальными нужно быть осторожными.

Ключевые вопросы параграфа

  • Как создавать собственные функции и зачем они нужны?
  • Что такое аргументы функции и как они передаются?
  • Как работает оператор return и какие значения может возвращать функция?
  • Что такое область видимости? Чем различаются локальные и глобальные переменные?
  • Как безопасно изменять переменные, переданные в функцию?

Как создавать собственные функции и зачем они нужны

Вы уже познакомились с некоторыми встроенными функциями Python — например, print(), input(), max(), min() и другими.

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

Функции позволяют:

  • переиспользовать один и тот же код без копирования;
  • сделать программу более читаемой и структурированной — за счёт разделения логики на небольшие, понятные блоки.

Синтаксис функции

Вот как выглядит базовое определение функции в Python:

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
9print(only_even([2, 4, 6]))
10print(only_even([1, 2, 3]))
11
12# Вывод программы:
13# True
14# False

Как работает оператор return и какие значения может возвращать функция

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

Пример: перепишем функцию only_even так, чтобы сразу возвращать результат без использования флага result:

1def only_even(numbers):
2    for x in numbers:
3        if x % 2 != 0:
4            return False
5    return True
6
7print(only_even([2, 4, 6]))
8print(only_even([1, 2, 3]))
9
10# Вывод программы:
11# True
12# False

Если в функции отсутствует return или он используется без значения, Python всё равно вернёт специальный объект None. Это тип, обозначающий отсутствие результата.

Пример:

1print(print("Эту строку выведет функция до возврата значения."))
2
3# Вывод программы:
4# Эту строку выведет функция до возврата значения.
5# None

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

1def only_even(numbers):
2    for i, x in enumerate(numbers):
3        if x % 2 != 0:
4            return False, i
5    return True
6
7print(only_even([2, 4, 6]))
8print(only_even([1, 2, 3]))
9
10# Вывод программы:
11# True
12# (False, 0)

Обратите внимание: в первом случае функция возвращает значение логического типа (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
7print(numbers)
8
9# Вывод программы:
10# NameError: name 'numbers' is not defined

Ошибка возникла потому, что переменная numbers определена как аргумент функции и существует только в момент её выполнения. Такая переменная находится в локальной области видимости.

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

Пример:

1def check_password(pwd):
2    return pwd == password
3
4password = "Python"
5print(check_password("123"))
6
7# Вывод программы:
8# False

В этом случае переменная password определена глобально и доступна внутри функции check_password.

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

Как безопасно изменять переменные, переданные в функцию

Можно ли изменить переменную из глобальной области видимости внутри функции? Ответ зависит от типа данных переменной:

  • Если это изменяемый тип (например, список), то изменение происходит напрямую.
  • Если это неизменяемый тип (например, число или строка), то попытка изменить значение создаёт локальную копию с тем же именем.

Рассмотрим пример с изменяемым типом — списком:

1def list_modify():
2    del sample[-1]
3
4sample = [1, 2, 3]
5list_modify()
6print(sample)
7# Вывод программы:
8# [1, 2]

А теперь пример, где внутри функции происходит присваивание нового значения списку:

1def list_modify():
2    sample = [4, 5, 6]
3
4sample = [1, 2, 3]
5list_modify()
6print(sample)
7
8# Вывод программы:
9# [1, 2, 3]

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

То же самое касается аргументов функции. Они ведут себя как локальные переменные:

1def list_modify_1(list_arg):
2    # создаём новый локальный список, не имеющий связи с внешним
3    list_arg = [1, 2, 3, 4]
4
5def list_modify_2(list_arg):
6    # меняем исходный внешний список, переданный как аргумент
7    list_arg += [4]
8
9sample_1 = [1, 2, 3]
10sample_2 = [1, 2, 3]
11list_modify_1(sample_1)
12list_modify_2(sample_2)
13print(sample_1)
14print(sample_2)
15
16# Вывод программы:
17# [1, 2, 3]
18# [1, 2, 3, 4]

Во втором случае список действительно изменился, потому что операция += модифицирует объект на месте.

Если вам всё же нужно изменить глобальную переменную внутри функции, это можно сделать с помощью ключевого слова global:

1def inc():
2    global x
3    x += 1
4    print(f"Количество вызовов функции равно {x}.")
5
6x = 0
7inc()
8inc()
9inc()
10
11# Вывод программы:
12
13# Количество вызовов функции равно 1.
14# Количество вызовов функции равно 2.
15# Количество вызовов функции равно 3.

Однако использовать global нужно с осторожностью. Глобальные переменные делают код менее предсказуемым: любое изменение может произойти в любой части программы, и это затрудняет отладку.

Обычно лучше передавать значения в функцию и возвращать результат, как показано ниже:

1def f(count):
2    count += 1
3    print(f'Количество вызовов функции равно {count}.')
4    return count
5
6count_f = 0
7count_f = f(count_f)
8count_f = f(count_f)
9count_f = f(count_f)
10
11# Вывод программы:
12# Количество вызовов функции равно 1.
13# Количество вызовов функции равно 2.
14# Количество вызовов функции равно 3.

✅ У вас получилось разобраться с функциями из этого параграфа?

👉 Оценить этот параграф

Что дальше

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

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

Дальше вас ждёт следующий шаг — гибкие способы передачи аргументов и работа с функциями как объектами. Мы поговорим про позиционные и именованные аргументы, значения по умолчанию, а также научимся передавать в функции другие функции. Вы узнаете, что такое *args, **kwargs, как устроены функции высшего порядка и зачем нужны лямбда-выражения.

А пока вы не ушли дальше — закрепите материал на практике:

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

Хотите обсудить, задать вопрос или не понимаете, почему код не работает? Мы всё предусмотрели — вступайте в сообщество Хендбука! Там студенты помогают друг другу разобраться.

Ключевые выводы параграфа

  • Функции позволяют переиспользовать код, делить программу на логические блоки и повышать читаемость.
  • Аргументы функции — это переменные, значения которых передаются при вызове и доступны только внутри функции (локальная область видимости).
  • Оператор return завершает выполнение функции и возвращает результат. Если return не указан, функция возвращает None.
  • Функция может возвращать сразу несколько значений — в этом случае они автоматически упаковываются в кортеж.
  • Локальные и глобальные переменные различаются по области действия: локальные живут только внутри функции, а глобальные доступны во всей программе. Изменять глобальные переменные внутри функции стоит только при необходимости: обычно лучше передавать значения через аргументы и возвращать результат.

Отмечайте параграфы как прочитанные чтобы видеть свой прогресс обучения

Вступайте в сообщество хендбука

Здесь можно найти единомышленников, экспертов и просто интересных собеседников. А ещё — получить помощь или поделиться знаниями.
Вступить
Сообщить об ошибке
Предыдущий параграф3.6. Чему вы научились
Следующий параграф4.2. Позиционные и именованные аргументы. Функции высших порядков. Лямбда-функции

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

Функции на максималках

Лямбда-функции отлично подходят для компактных вычислений, а их потенциал можно раскрыть ещё больше, развернув их в облаке. С помощью Yandex Cloud Functions функции становятся доступными из любого места, позволяя автоматизировать обработку данных, создавать API и реализовывать масштабируемые решения.