В программировании на Python понятия функция и метод являются базовыми строительными блоками. Простыми словами, функция — это именованный фрагмент кода, который выполняет определённую задачу и может принимать входные данные (аргументы), а затем возвращать результат. Метод — это функция, связанна с объектом или классом; она оперирует состоянием этого объекта. Понимание различий и сходств между ними помогает писать более структурированный и повторно используемый код. В учебном стиле это удобно рассматривать как алгоритм: выделить вход, обработать и вернуть выход — это основа любой функции.
Синтаксис объявления функции в Python начинается с ключевого слова def: например, def add(a, b): return a + b. Пошагово выполнение выглядит так: 1) Python видит объявление и создаёт объект функции; 2) при вызове add(2, 3) интерпретатор создаёт локальную область видимости для параметров a и b; 3) выполняется тело функции; 4) выдаётся результат 5. Документирование важно: сразу после заголовка функции полезно добавить строку-докстринг (три кавычки) с описанием поведения, аргументов и возвращаемого значения. Пример: def greet(name: str) -> str: """Возвращает приветствие для name.""" return f"Привет, {name}!". Такой подход облегчает поддержку кода и генерацию документации.
Аргументы — одно из ключевых понятий: есть позиционные, именованные, по умолчанию и специальные формы *args и **kwargs. Позиционные передаются по порядку: def f(a, b):..., именованные — указываются как f(b=2, a=1). Значения по умолчанию позволяют вызывать функцию без указания всех параметров: def power(x, n=2): return x**n. Важное предупреждение: не используйте изменяемые объекты в качестве значений по умолчанию (например, список), потому что один и тот же объект будет разделяться между вызовами. Примеры с *args и **kwargs: def do(*args, **kwargs): print(args, kwargs) — удобно для функций-обёрток и гибких интерфейсов.
Область видимости переменных и правила поиска имён (LEGB — Local, Enclosing, Global, Built-in) — обязательны к пониманию. Локальные переменные существуют только внутри тела функции; глобальные — на уровне модуля. Ключевые слова global и nonlocal управляют доступом: global позволяет изменять глобальную переменную внутри функции, nonlocal — изменять переменную из внешней функции в случае вложенных (замыкание). Пример замыкания: def outer(x): def inner(y): return x + y return inner — inner «захватывает» x и может использоваться позже. Замыкания полезны для создания настраиваемых функций без хранения состояния в глобальных переменных.
Анонимные функции (lambda) и функции высшего порядка — следующая тема. Lambda выражения позволяют быстро описать простую функцию: lambda x, y: x * y. Их часто используют вместе с map, filter и sorted. Примеры: list(map(lambda x: x*2, [1,2,3])) -> [2,4,6]; list(filter(lambda x: x%2==0, range(6))) -> [0,2,4]. Функции высшего порядка — это те, что принимают функции как аргументы или возвращают их. Это мощный паттерн для абстракции. Например, def make_multiplier(n): return lambda x: x * n — возвращает функцую-умножитель.
Переходим к методам в классах: методы экземпляра получают первым параметром self и оперируют атрибутами объекта. Пример: class Counter: def __init__(self): self.count = 0 def inc(self): self.count += 1. Существуют также classmethod и staticmethod. @classmethod получает cls и работает с самим классом (например, альтернативные конструкторы), @staticmethod не получает ни self, ни cls и ведёт себя как обычная функция, логически сгруппированная с классом. Пример classmethod: @classmethod def from_list(cls, items): obj = cls() ... return obj. Понимание концепции связывания методов (bound methods) помогает: при обращении instance.method Python автоматически подставляет instance в качестве self.
Декораторы — это удобный инструмент для изменения поведения функций без изменения их кода. Декоратор — это функция, которая принимает функцию и возвращает новую функцию. Часто используют синтаксис @decorator над определением функции. Простой пример: def timer(func): def wrapper(*a, **k): import time; t0 = time.time(); res = func(*a, **k); print(time.time() - t0); return res; return wrapper. Для корректного сохранения метаданных функции применяют functools.wraps. Декораторы дают возможность логирования, проверки прав, кэширования (memoization) и т.д.
Рекурсия — приём, когда функция вызывает саму себя. Это естественно для задач, представимых через разбиение на подобные подзадачи: вычисление факториала, обход дерева, поиск в глубину. Пример факториала: def fact(n): return 1 if n<=1 else n*fact(n-1). Нужно учитывать глубину рекурсии и стек вызовов: в Python есть ограничение sys.getrecursionlimit(), которое при необходимости можно увеличить, но часто более эффективным будет перевод рекурсии в цикл или использование алгоритмов с явным стеком.
Важно знать о встроенных методах для стандартных типов: список имеет методы append, extend, insert, pop, remove, sort, reverse; строка — split, join, replace, lower, upper, strip; словарь — keys, values, items, get, setdefault, update. Это не просто удобство — использование встроенных методов часто более эффективно, чем написание эквивалентного цикла вручную. Например, для объединения списка строк prefer "sep.join(list_of_strings)" вместо последовательных конкатенаций.
Аннотации типов и докстринги делают код понятнее и пригодным для статического анализа. Пример аннотаций: def add(a: int, b: int) -> int: return a + b. Использование mypy или PyCharm помогает находить ошибки до выполнения. Докстринг по стандарту PEP 257 должен включать короткое описание поведения функции и, при необходимости, разделы Args, Returns, Raises. Следование PEP8 именованию (snake_case для функций, lower_case_with_underscores) улучшает читаемость и восприятие кода командой.
Практические советы и распространённые ошибки: 1) Не забывайте про return — отсутствие return возвращает None, что часто становится источником ошибок. 2) Избегайте использования изменяемых значений по умолчанию. 3) Не используйте имена встроенных функций для переменных (например, list, dict, str). 4) Пишите маленькие функции — каждая должна делать одно действие (принцип единственной ответственности). 5) Покрывайте функции тестами (unit tests), описывайте граничные случаи. 6) Профилируйте длительные операции и используйте алгоритмическую оптимизацию перед микроскопической оптимизацией.
Шаги проектирования хорошей функции — полезная памятка:
В заключение: освоение функций и методов в Python — путь к созданию чистого, модульного и легко поддерживаемого кода. Понимание синтаксиса, области видимости, типов аргументов, декораторов и методов классов позволит вам проектировать гибкие API и избегать типичных ошибок. Рекомендуется практиковаться на небольших задачах: реализовать утилиты для работы со строками, написать класс с несколькими методами и декораторами, и попробовать профилировать разные реализации. Такой пошаговый и осознанный подход быстро повысит качество ваших программ и навыки программирования.