Функции: параметры, возвращаемые значения, область видимости🔗
Функции как кулинарные заготовки: зачем декомпозировать код🔗
Представьте, что вы готовите три блюда, и каждое требует бешамель: вместо того чтобы переписывать рецепт соуса каждый раз, проще использовать готовую заготовку. В программировании та же логика применяется к повторяющимся блокам кода. Их дублирование нарушает принцип DRY (Don't Repeat Yourself): при изменении логики придётся править каждую копию, что множит ошибки.
Чтобы избежать этого, используют функции — именованные блоки инструкций, которые создаются однажды и применяются многократно. Подобно полуфабрикату, который хранится отдельно от готового блюда, функция существует в памяти независимо от основного потока выполнения.
Важно различать два состояния. Определение функции (def) — это как запись рецепта в книгу: оно лишь фиксирует инструкции, но не запускает их выполнение. Вызов функции (name()) — момент, когда интерпретатор начинает пошагово исполнять записанные команды.
def make_behamel():
milk = 500
flour = 50
butter = 50
sauce = milk + flour + butter # упрощенно
print("Соус готов:", sauce, "г")
# Определение создано, но код внутри ещё не выполнялся
make_behamel() # Теперь инструкции выполняются
make_behamel() # И снова, без дублирования кода
Диаграмма загружается…
Параметры и аргументы: передача ингредиентов в функцию🔗
В кулинарной книге рецепт содержит обобщённые названия — «тесто», «начинка». При приготовлении вы подставляете конкретные продукты: слоёное тесто и яблоки. В коде параметры — это имена в скобках при определении def, а аргументы — фактические значения, передаваемые при вызове.
Передача данных может быть строго упорядоченной. При позиционном способе значения распределяются по порядку: первое → первому параметру, второе → второму:
def calculate_area(length, width):
return length * width
# 5 станет length, 3 станет width
s = calculate_area(5, 3)
Перепутайте аргументы — получите неверный результат, как если бы посолили кофе вместо сахара.
Именованные аргументы позволяют при вызове явно указать целевой параметр, игнорируя порядок: calculate_area(width=3, length=5).
Чтобы зафиксировать значение заранее, используют параметры по умолчанию. Они делают часть аргументов необязательной, как стандартная поставка без заказа:
def greet(name, greeting="Привет"):
return greeting + ", " + name
# Достаточно одного аргумента
msg = greet("Анна")
| Способ передачи |
Синтаксис вызова |
Кулинарная аналогия |
| Позиционный |
calculate_area(5, 3) |
Порядок слоёв в торте |
| Именованный |
calculate_area(width=3) |
Этикетка на контейнере |
| По умолчанию |
Пропуск в вызове |
Базовый комплект |
Именно различие между именами в определении функции и реальными данными при вызове позволяет использовать код многократно.
Возвращаемые значения: результат приготовления🔗
Когда блюдо готово, повар передаёт его через окно выдачи — не оставляет же он просто на плите. Оператор return делает то же самое: возвращает результат работы функции в вызывающий код, выдавая готовый продукт вместо пустой тарелки.
Функции, вычисляющие значения, отличаются от процедур, которые просто выполняют действия. В Python функция без return автоматически возвращает None — это как получить пустую упаковку вместо обеда. Здесь принципиальная разница: одни операции меняют состояние системы, другие порождают данные.
Чтобы использовать результат дальше, сохраните его в переменной:
def mix_sugar_and_butter(sugar, butter):
cream = sugar + butter
return cream
# Забираем результат через "окно выдачи" в переменную
dough_base = mix_sugar_and_butter(200, 150)
print(dough_base)
Часто нужно вернуть сразу несколько элементов — скажем, муку и воду для теста. Перечислите их через запятую: Python соберёт их в кортеж (подробнее о коллекциях — в лекции 8). Пока важно понять, что результат можно сразу распаковать в несколько переменных:
def prepare_dough():
flour = 300
water = 150
return flour, water
f, w = prepare_dough()
Переменные f и w получают значения одновременно — точно так же, как если бы вы разложили ингредиенты по разным ёмкостям. Дальше мы выясним, где именно живут эти переменные — в общем доступе или в изолированной зоне функции.
Область видимости: кухня vs кладовая🔗
В ресторане действует негласное правило: что лежит на рабочем столе повара — принадлежит только ему. Ингредиенты появляются там в начале смены и исчезают, когда повар уходит. В программировании это локальные переменные: они создаются при входе в функцию и уничтожаются при выходе.
Общий склад, откуда любой может взять соль или масло, — это глобальные переменные. Они существуют на протяжении всей работы программы.
def make_sauce():
butter = 100 # локальная переменная — на рабочем столе
print(butter)
make_sauce()
print(butter) # NameError: name 'butter' is not defined
Диаграмма загружается…
Как только функция завершается, локальная область очищается автоматически. Попытка обратиться к butter извне приводит к ошибке — контейнера больше не существует.
В Python есть ключевое слово global, позволяющее писать прямо в кладовую из кухни. Это крайняя мера: такой код порождает скрытые связи между удалёнными частями программы и непредсказуемые побочные эффекты. Лучше передавать данные через параметры и return, а не через глобальное пространство.