Основы программирования

Функции

**Загадка:** Есть код для расчёта скидки. Он нужен в 20 местах программы. Копировать 20 раз? А если нужно изменить формулу - менять в 20 местах? Функции решают эту проблему раз и навсегда.

Функция - это именованный блок кода, который можно вызывать сколько угодно раз. Встроенные функции print(), len(), range() работают по той же механике, а в этом уроке - создание собственных.

Цели урока

  • Понять что такое функция и зачем она нужна
  • Научиться создавать функции с параметрами
  • Освоить возврат значений (return)
  • Понять разницу между параметрами и аргументами

Предварительные знания

  • Переменные и типы (урок 3)
  • Условные операторы (урок 6)
  • Циклы (урок 7)

Каждое приложение - это набор функций. Нажал кнопку "Купить"? Вызвалась функция process_payment(). Отправил сообщение? Функция send_message(). Функции - это кирпичики программ.

  • **API**: каждый endpoint - это функция на сервере
  • **Библиотеки**: pandas, numpy, requests - наборы функций
  • **Игры**: move_player(), check_collision(), render_frame()
  • **Бизнес**: calculate_tax(), send_invoice(), generate_report()

От лямбда-исчисления Чёрча до стрелочных функций JavaScript

Идея функции как объекта старше любого языка программирования. В 1936 году Алонзо Чёрч в Принстоне формализовал лямбда-исчисление: математическую модель вычислений, где всё построено на анонимных функциях и их применении. На той же конференции Алан Тьюринг (ученик Чёрча) показал, что лямбда-исчисление и машина Тьюринга равно мощны. На практике подпрограмма как переиспользуемый блок появилась в работах Грейс Хоппер в конце 1940-х на компьютере UNIVAC: она первой назвала библиотеку готовых блоков subroutines. В 1958 году Джон Маккарти в MIT создал Lisp, где функции стали first-class объектами: их можно передавать как аргументы, возвращать как результат, хранить в переменных. В 1972 году Деннис Ритчи в C добавил указатели на функции: первое практическое first-class из мейнстрима. В 1995 году Брендан Эйх за десять дней сделал JavaScript с функциями как объектами, что подготовило почву для функционального стиля в вебе. В 2015 году ES6 добавил стрелочные функции: const f = x => x * 2, лексический this, компактный синтаксис. Сегодня анонимные функции есть везде: lambda в Python, fn в Rust, замыкания в Kotlin и Swift. Идея Чёрча 1936 года теперь крутится в каждом браузере, на каждом сервере, в каждом приложении.

Создание функции: def

**def** (define) - ключевое слово для создания функции. После него - имя функции и круглые скобки.

Простейшая функция

Определение и вызов

```python # Определение функции def greet(): print("Привет!") print("Как дела?") # Вызов функции greet() # Привет! Как дела? greet() # Можно вызывать сколько угодно раз! ``` **Структура:** 1. `def` - ключевое слово 2. `greet` - имя функции (как переменная, snake_case) 3. `()` - скобки для параметров (пока пустые) 4. `:` - двоеточие в конце строки 5. Тело функции - с отступом

**Определение ≠ Выполнение!** Код внутри функции НЕ выполняется до явного вызова. `def greet():` просто создаёт функцию, а `greet()` - вызывает её.

Что произойдёт при выполнении кода? ```python def hello(): print("Hello") ```

Параметры: входные данные

**Параметры** - переменные в скобках при определении функции. Они получают значения при вызове.

Функция с параметром

Персонализированное приветствие

```python # name - параметр (placeholder) def greet(name): print(f"Привет, {name}!") # При вызове передаём аргумент greet("Алиса") # Привет, Алиса! greet("Боб") # Привет, Боб! # Несколько параметров def greet_full(first_name, last_name): print(f"Здравствуйте, {first_name} {last_name}!") greet_full("Иван", "Петров") # Здравствуйте, Иван Петров! ```

**Параметр vs Аргумент:** - **Параметр** - переменная в определении: `def greet(name)` - **Аргумент** - конкретное значение при вызове: `greet("Алиса")`

Функция-калькулятор

Расчёт с параметрами

```python def calculate_area(width, height): area = width * height print(f"Площадь: {area}") calculate_area(5, 3) # Площадь: 15 calculate_area(10, 2) # Площадь: 20 # Порядок аргументов важен! calculate_area(3, 5) # То же самое, но аргументы в другом порядке ```

Что выведет код? ```python def add(a, b): print(a + b) add(3, 5) ```

return: возврат результата

**return** - возвращает значение из функции. Функция превращается в "машину", которая принимает входные данные и выдаёт результат.

Функция с return

Вместо print - return

```python # Без return (только печатает) def add_print(a, b): print(a + b) # Просто выводит # С return (возвращает значение) def add(a, b): return a + b # Возвращает результат # Разница: add_print(3, 5) # Выведет 8, но результат "пропадёт" result = add(3, 5) # result = 8, можно использовать дальше! print(result * 2) # 16 total = add(add(1, 2), add(3, 4)) # 1+2 + 3+4 = 10 ```

**return прерывает функцию!** Код после return не выполнится. Это можно использовать для раннего выхода.

Ранний return

Выход при условии

```python def divide(a, b): if b == 0: return None # Ранний выход при ошибке return a / b print(divide(10, 2)) # 5.0 print(divide(10, 0)) # None (деление на 0) ```

print() и return - одно и то же

print() выводит на экран, return - возвращает значение для дальнейшего использования

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

Что будет в x? ```python def mystery(n): return n * 2 print("Done") x = mystery(5) ```

Значения по умолчанию

Параметрам можно задать **значения по умолчанию**. Если аргумент не передан - используется default.

Параметры со значениями по умолчанию

Опциональные аргументы

```python def greet(name, greeting="Привет"): print(f"{greeting}, {name}!") greet("Алиса") # Привет, Алиса! greet("Боб", "Здравствуй") # Здравствуй, Боб! greet("Вика", greeting="Хай") # Хай, Вика! # Практический пример def power(base, exponent=2): return base ** exponent print(power(5)) # 25 (5²) print(power(5, 3)) # 125 (5³) ```

**Правило:** параметры со значениями по умолчанию должны идти ПОСЛЕ обычных параметров. `def f(a=1, b)` - ошибка!

Именованные аргументы

Явное указание параметра

```python def create_user(name, age, city="Неизвестно", active=True): print(f"{name}, {age} лет, {city}, активен: {active}") # Позиционные аргументы (по порядку) create_user("Алиса", 25, "Москва", False) # Именованные аргументы (в любом порядке) create_user(name="Боб", age=30, active=False) create_user("Вика", 28, active=False) # Смешанный вариант ```

Что выведет? ```python def f(a, b=10): return a + b print(f(5)) ```

Возврат нескольких значений

Python позволяет возвращать несколько значений через запятую. Технически это кортеж (tuple).

Множественный return

Несколько значений одновременно

```python def min_max(numbers): return min(numbers), max(numbers) # Распаковка результата minimum, maximum = min_max([3, 1, 4, 1, 5]) print(f"Min: {minimum}, Max: {maximum}") # Min: 1, Max: 5 # Или как кортеж result = min_max([3, 1, 4, 1, 5]) print(result) # (1, 5) # Практика: деление с остатком def divmod_custom(a, b): quotient = a // b remainder = a % b return quotient, remainder q, r = divmod_custom(17, 5) print(f"17 = 5 × {q} + {r}") # 17 = 5 × 3 + 2 ```

Что будет в a и b? ```python def swap(x, y): return y, x a, b = swap(1, 2) ```

Документирование функций

**Docstring** - строка документации в начале функции. Описывает что делает функция, какие параметры принимает, что возвращает.

Docstring в действии

Документируй свои функции

```python def calculate_bmi(weight, height): """ Вычисляет индекс массы тела (BMI). Args: weight: Вес в килограммах height: Рост в метрах Returns: BMI как float Example: >>> calculate_bmi(70, 1.75) 22.86 """ return weight / (height ** 2) # Доступ к документации print(calculate_bmi.__doc__) help(calculate_bmi) # Красивый вывод в консоли ```

В IDE (VS Code, PyCharm) docstring показывается при наведении на функцию. Пиши их для функций, которые будешь использовать повторно!

Где размещается docstring в функции?

Связь с другими темами

Функции лежат в основе почти всех абстракций программирования:

  • Рекурсия — Функция вызывает саму себя, заменяя цикл явной декомпозицией задачи
  • Область видимости — Параметры и локальные переменные живут в кадре стека функции
  • Объекты — Методы это функции, привязанные к объекту через self
  • Рефакторинг — Extract Function самый частый приём: разбить длинный код на маленькие функции

Итог

  • def создаёт именованную функцию: имя, параметры, тело с отступом
  • Параметры это переменные в определении, аргументы это конкретные значения при вызове
  • return возвращает значение и немедленно завершает функцию, без return функция вернёт None
  • Значения по умолчанию делают параметры опциональными, должны идти после обязательных
  • Именованные аргументы (name=value) позволяют передавать параметры в любом порядке
  • Чистая функция зависит только от своих аргументов и не имеет побочных эффектов: проще тестировать

Вопросы для размышления

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

Связанные уроки

  • prog-06-conditionals — Функции содержат ветвление чтобы менять поведение
  • prog-10-scope — Каждый вызов функции создаёт свою область видимости
  • prog-09-recursion — Рекурсия это функция вызывающая саму себя
  • la-07-matrix-multiply — Функция отображает входы в выходы как преобразование
  • mm-02-first-principles
  • alg-01-big-o
Функции

0

1

Войти