Функции в Python

Ключевые тезисы

  • Функции — это подпрограммы для структурирования кода и избежания повторов.
  • Функция может принимать параметры и возвращать результат.
  • Параметры могут быть позиционными, именованными и иметь значения по умолчанию.
  • В Python используется утиная типизация: функция работает с любыми объектами, поддерживающими нужные операции.
  • Вызов функции синхронный: управление возвращается в точку вызова после её завершения.
  • Важен подход проектирования «сверху вниз»: от общей задачи к деталям реализации.

Основное содержание

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

Простая функция определяется с помощью ключевого слова def. Тело функции сдвигается на 4 пробела.

def hello():
    print("Hello world")

Вызов функции происходит с использованием круглых скобок: hello(). Без скобок имя функции становится ссылкой на объект-функцию.

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

Функция может принимать параметры, которые указываются в скобках при её определении (формальные параметры).

def hello(name):
    print("Hello", name)

При вызове функции передаются фактические параметры: hello("John").

Параметры по умолчанию и именованные параметры

Параметру можно задать значение по умолчанию. Это позволяет вызывать функцию без указания этого аргумента.

def hello(name="world"):
    print("Hello", name)

При вызове можно явно указывать, какому параметру какое значение присваивается (именованные параметры). Это позволяет менять порядок аргументов.

def hello_separated(name="world", sep="-"):
    print("Hello", name, sep=sep)

hello_separated(sep="***", name="John")  # Именованные параметры

Возврат значения

Для возврата результата из функции используется инструкция return. Она немедленно завершает выполнение функции.

def max2(x, y):
    if x > y:
        return x
    return y

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

def max3(x, y, z):
    return max2(x, max2(y, z))

Утиная типизация

В Python не требуется указывать типы параметров. Функция будет работать с любыми объектами, для которых определены используемые в ней операции (например, сравнение >). Если операция не поддерживается, возникнет ошибка во время выполнения.

Стек вызовов и синхронность

Вызов функции является синхронным: программа «засыпает», передавая управление функции, и «просыпается», когда та вернёт результат.
Цепочка вызовов функций (A → B → C) управляется с помощью стека вызовов (call stack). В стек помещается информация о том, куда нужно вернуться после выполнения каждой функции. При возникновении ошибки интерпретатор выводит содержимое стека, что помогает понять контекст ошибки.

Проектирование «сверху вниз»

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

  1. Взлёт (мечтание): Определяется главная функция с её параметрами и возвращаемым значением. Внутри неё намечаются вызовы других, ещё не существующих функций.
  2. Приземление: Создаются «заглушки» для намеченных функций (например, с помощью pass). Программа становится целостной и выполнимой, но не делает полезной работы.
  3. Детализация: Каждая функция-заглушка постепенно наполняется реальной логикой, возможно, с дальнейшим разбиением на подфункции.

Примеры алгоритмов

Проверка числа на простоту (метод грубой силы)

Алгоритм перебирает возможные делители числа.

def is_simple(x):
    """Определяет, является ли число простым."""
    divisor = 2
    while divisor < x:
        if x % divisor == 0:
            return False
        divisor += 1
    return True

Разложение числа на множители (факторизация)

Алгоритм последовательно делит число на найденные простые делители.

def factorize(x):
    """Разлагает число на множители и печатает их."""
    divisor = 2
    while x > 1:
        if x % divisor == 0:
            print(divisor)
            x //= divisor
        else:
            divisor += 1

Выводы

  • Функции — ключевой инструмент для структурирования кода и реализации принципа «разделяй и властвуй».
  • Правильное именование функций и использование документ-строк ("""docstring""") критически важно для читаемости и поддерживаемости кода.
  • Метод проектирования «сверху вниз» позволяет управлять сложностью, разбивая большую задачу на последовательность маленьких и понятных шагов.