Функции и области видимости
Тема дорожной карты · Python Programming
Функции, объявленные через def или lambda, являются первоклассными объектами в Python, что позволяет передавать их, возвращать из других функций и даже добавлять атрибуты. Это делает функции мощным инструментом для организации и повторного использования кода. Важность понимания областей видимости и правил скоупинга неоценима, так как они помогают избежать распространенных ошибок и улучшают читаемость и поддерживаемость кода.
Как это работает
Функции и области видимости используются для организации кода и обеспечения повторного использования. Объявление функции осуществляется с помощью ключевого слова def, за которым следует имя функции и её параметры. Параметры могут быть позиционными, именованными, иметь значения по умолчанию, быть вариадическими (*args, **kwargs) или быть позиционно- или именованно-только (PEP 570/3102). Вызов функции осуществляется через ключевое слово return, которое возвращает значение функции (или None, если значение не указано). Функции являются первоклассными объектами, что означает, что их можно присваивать переменным, передавать как аргументы другим функциям и возвращать из других функций.
Анонимные функции, объявленные через lambda, полезны для создания коротких, однострочных функций. Они часто используются в контексте sorted(key=...), map, filter и других функциях, где требуется быстрое создание функции на лету. Правила скоупинга в Python определяются правилом LEGB, которое означает Local, Enclosing, Global, Built-in. Это означает, что поиск переменных начинается с локальной области видимости, затем переходит к области видимости, окружающей текущую функцию, затем к глобальной области видимости и, наконец, к встроенным объектам.
Когда применять
Функции следует выносить, когда код повторяется, когда ему можно дать осмысленное имя и когда вы хотите тестировать его изолированно. Предпочтение следует отдавать чистым функциям (без побочных эффектов, детерминированным) там, где это возможно, так как они легче композируются и тестируются. Важно использовать *args и **kwargs с осторожностью, так как они могут привести к неочевидным ошибкам. Явные параметры лучше, так как они документируют намерение. lambda полезна для создания маленьких встроенных коллбэков, но для более сложных функций следует использовать def с именем.
Типичные ошибки
Одной из распространенных ошибок является использование изменяемого значения по умолчанию, например, def f(x=[]):. В этом случае список будет общий для всех вызовов функции. Чтобы избежать этой проблемы, следует использовать None как маркер и создавать контейнер уже внутри тела функции. Другой распространенной ошибкой является затенение встроенных имён локальными переменными, например, list = [1,2]. Это может привести к непредсказуемому поведению, когда вы пытаетесь использовать встроенные функции, такие как list(). Также важно избегать глубоко вложенных замыканий, которые захватывают переменные цикла по ссылке, а не по значению. Это может привести к непредсказуемому поведению и трудностям при отладке.