На этом шаге мы рассмотрим особенности такого поведения.
Вы только что увидели, что функции могут содержать внутренние функции и что даже существует возможность возвращать эти (в других ситуациях скрытые) внутренние функции из родительской функции.
Мы собираемся зайти на территорию функционального программирования еще дальше.
Мало того что функции могут возвращать другие функции, эти внутренние функции также могут захватывать и уносить с собой часть состояния родительской функции. И что же это означает?
Чтобы это проиллюстрировать, мы собираемся немного переписать предыдущий пример функции 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)() 'ПРИВЕТ, МИР!'
Хотя в 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__() этого объекта.
Безусловно, не все объекты будут вызываемыми. Вот почему существует встроенная функция callable(), которая проверяет, является объект вызываемым или нет:
>>> callable(plus_3) True >>> callable(yell) True >>> callable('привет') False
На следующем шаге мы подведем краткие итоги.