Простой Python. Современный стиль программирования (Любанович) - страница 67

>add_args(5, 9)

Вы можете объединить этот прием с использованием *args и **kwargs.

Определим тестовую функцию, которая принимает любое количество позиционных аргументов, определяет их сумму с помощью функции sum() и возвращает ее:

>>>> def sum_args(*args):

>…····return sum(args)

Я не упоминал функцию sum() ранее. Это встроенная в Python функция, которая высчитывает сумму значений итерабельного числового (целочисленного или с плавающей точкой) аргумента.

Мы определим новую функцию run_with_positional_args(), принимающую функцию и произвольное количество позиционных аргументов, которые нужно будет передать в нее:

>>>> def run_with_positional_args(func, *args):

>…····return func(*args)

Теперь вызовем ее:

>>>> run_with_positional_args(sum_args, 1, 2, 3, 4)

>10

Вы можете использовать функции как элементы списков, кортежей, множеств и словарей. Функции неизменяемы, поэтому вы можете даже применять их как ключи для словарей.

Внутренние функции

Вы можете определить функцию внутри другой функции:

>>>> 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, но не вызывает ее. Это и есть замыкание: динамически созданная функция, которая запоминает, откуда она появилась.