Вы можете определить функцию внутри другой функции:
>>> def outer(a, b):
…·····def inner(c, d):
…·········return c + d
…·····return inner(a, b)
…
>>>
>>> outer(4, 7)
11
Внутренние функции могут быть полезны при выполнении некоторых сложных задач более одного раза внутри другой функции. Это позволит избежать использования циклов или дублирования кода. Рассмотрим пример работы со строкой, когда внутренняя функция добавляет текст к своему аргументу:
>>> def knights(saying):
…·····def inner(quote):
…·········return "We are the knights who say: '%s'" % quote
…·····return inner(saying)
…
>>> knights('Ni!')
"We are the knights who say: 'Ni!'"
Замыкания
Внутренняя функция может действовать как
Следующий пример создан на основе предыдущего примера knights(). Назовем новую функцию knights2(), поскольку у нас нет воображения, и превратим функцию inner() в замыкание, которое называется inner2(). Различия заключаются в следующем.
• inner2() использует внешний параметр saying непосредственно, вместо того чтобы получить его как аргумент.
• knights2() возвращает имя функции inner2, вместо того чтобы вызывать ее:
>>> def knights2(saying):
…·····def inner2():
…·········return "We are the knights who say: '%s'" % saying
…·····return inner2
…
Функция inner2() знает значение переменой saying, которое было передано в функцию, и запоминает его. Строка inner2 возвращает эту особую копию функции inner2, но не вызывает ее. Это и есть замыкание: динамически созданная функция, которая запоминает, откуда она появилась.
Вызовем функцию knights2() два раза с разными аргументами:
>>> a = knights2('Duck')
>>> b = knights2('Hasenpfeffer')
О’кей, чем являются a и b?
>>> type(a)
>>> type(b)
Они являются функциями, а также замыканиями:
>>> a
>>> b
Если мы вызовем их, они запомнят значение переменной saying, которое было использовано, когда они были созданы функцией knights2:
>>> a()
"We are the knights who say: 'Duck'"
>>> b()
"We are the knights who say: 'Hasenpfeffer'"
Анонимные функции: функция lambda()
В Python
Для того чтобы проиллюстрировать анонимные функции, сначала создадим пример, в котором используются обычные функции. Для начала мы определим функцию edit_story(). Она имеет следующие аргументы:
• words — список слов;
• func — функция, которая должна быть применена к каждому слову в списке words:
>>> def edit_story(words, func):
…·····for word in words:
…·········print(func(word))
Теперь нам нужны список слов и функция, которую требуется к ним применить. В качестве слов я возьму список звуков (гипотетических), которые мог бы издать мой кот, если бы (гипотетически) он не заметил одну из лестниц:
>>> stairs = ['thud', 'meow', 'thud', 'hiss']
Функция же запишет с большой буквы каждое слово и добавит к нему восклицательный знак, что идеально подойдет для заголовка какой-нибудь желтой кошачьей газетенки:
>>> def enliven(word):···# больше эмоций!
…·····return word.capitalize() + '!'
Смешаем наши ингредиенты:
>>> edit_story(stairs, enliven)
Thud!
Meow!
Thud!
Hiss!
Наконец переходим к лямбде. Функция enliven() была такой короткой, что мы можем заменить ее лямбдой:
>>>
>>> edit_story(stairs, lambda word: word.capitalize() + '!')
Thud!
Meow!
Thud!
Hiss!
>>>
Лямбда принимает один аргумент, который в этом примере назван word. Все, что находится между двоеточием и закрывающей скобкой, является определением функции.