3 .1 . Функции Python — это объекты первого класса
73
Мало того что функции могут возвращать другие функции, эти внутрен-
ние функции также могут
захватывать и уносить с собой часть состояния
родительской функции. И что же это означает?
Чтобы это проиллюстрировать, я собираюсь немного переписать преды-
дущий пример функции
get_speak_func
. Новая версия сразу принимает
аргументы «
volume
» и «
text
», чтобы немедленно сделать возвращаемую
функцию вызываемой:
def get_speak_func(text, volume):
def whisper():
return text.lower() + '...'
def yell():
return text.upper() + '!'
if volume > 0.5:
return yell
else:
return whisper
>>> get_speak_func('Привет, Мир', 0.7)()
'ПРИВЕТ, МИР!'
Теперь взгляните на внутренние функции
whisper
и
yell
. Обрати-
ли
внимание на то, что у них больше нет параметра
text
? Но каким-
то непостижимым образом они по-прежнему могут получать доступ
к этому параметру
text
, определенному в родительской функции. На
самом деле они, похоже,
захватывают и «запоминают» значение этого
аргумента.
Функции, которые это делают, называются
лексическими замыканиями
(lexical closures) (или, для краткости, просто
замыканиями). Замыкание
помнит значения из своего лексического контекста, даже когда поток
управления программы больше не находится в этом контексте.
В практическом плане это означает, что функции могут не только
воз-
вращать линии поведения, но и предварительно
конфигурировать эти
линии поведения. Ниже приведен еще один скелетный пример, который
иллюстрирует эту идею:
def make_adder(n):
def add(x):
return x + n
74 Глава 3 •
Эффективные функции
return add
>>> plus_3 = make_adder(3)
>>> plus_5 = make_adder(5)
>>> plus_3(4)
7
>>> plus_5(4)
9
В данном примере
make_adder
служит
фабрикой для создания и кон-
фигурирования функций-«сумматоров». Обратите внимание на то, что
функции-«сумматоры» по-прежнему могут получать доступ к аргументу
n
функции
make_adder
(объемлющему контексту).
Объекты
могут вести себя как функции
Хотя в Python все функции являются объектами, обратное неверно.
Объекты не являются функциями. Но они могут быть сделаны
вызы-
ваемыми, что во многих случаях позволяет рассматривать их в качестве
функций.
Если объект является вызываемым, то это означает, что вы можете ис-
пользовать с ним синтаксис вызова функций с круглыми скобками и даже
передавать в него аргументы вызова функции. Все это приводится в дей-
ствие дандер-методом
__call__
. Ниже приведен пример класса, опреде-
ляющего вызываемый объект:
class Adder:
def __init__(self, n):
self.n = n
def __call__(self, x):
return self.n + x
>>> plus_3 = Adder(3)
>>> plus_3(4)
7
За кадром «вызов» экземпляра объекта в качестве функции сводится
к исполнению метода
__call__
этого объекта.
3 .2 . Лямбды — это
функции одного выражения 75
Безусловно, не все объекты будут вызываемыми. Вот почему существует
встроенная функция
callable
, которая проверяет, является объект вы-
зываемым или нет:
>>> callable(plus_3)
True
>>> callable(yell)
True
>>> callable('привет')
False
Ключевые выводы
В Python абсолютно все является объектом, включая функции. Их
можно присваивать переменным, хранить в структурах данных и пере-
давать или возвращать в другие функции и возвращать из них (функ-
ции первого класса).
Функции первого класса позволяют абстрагироваться и раздавать
линии поведения в ваших программах.
Функции могут быть вложенными, и они могут захватывать и уносить
с собой часть состояния родительской функции. Функции, которые это
делают, называются замыканиями.
Объекты можно делать вызываемыми. Во многих случаях это позво-
ляет рассматривать их в качестве функций.
3 .2 . Лямбды — это
функции одного выражения
Ключевое слово
lambda
в Python предоставляет краткую форму для
объявления небольших анонимных функций. Лямбда-функции ведут
себя точно так же,
как обычные функции, объявляемые ключевым сло-
вом
def
. Они могут использоваться всякий раз, когда требуются объ-
екты-функции.
Например, ниже показано определение простой лямбда-функции, вы-
полняющей сложение:
76 Глава 3 • Эффективные функции
>>> add = lambda x, y: x + y
>>> add(5, 3)
8
Та же самая функция
add
может быть определена при помощи ключевого
слова
def
, но она была бы чуть-чуть многословнее:
>>> def add(x, y):
... return x + y
>>> add(5, 3)
8
Сейчас вы, вероятно, задаетесь вопросом: «Что за шум вокруг этих лямбд?
Если они нечто иное, чем слегка укороченная версия объявления функций
при
помощи ключевого слова
def
, то что тут такого-то?»
Взгляните на приведенный ниже пример и держите слова «
функциональ-
Do'stlaringiz bilan baham: