Так как функции в языке Python являются объектами, можно написать такую программу, которая будет работать с ними, как с обычными объектами. Объекты функции могут присваиваться, передаться другим функциям, сохраняться в структурах данных и так далее, как если бы они были простыми числами или строками.
Кроме того, объекты функций поддерживают специальные операции: они могут вызываться перечислением аргументов в круглых скобках, следующих сразу же за выражением функции. И тем не менее, функции принадлежат к категории обычных объектов.
Мы встречали уже такие способы использования функций в более ранних примерах, тем не менее краткий обзор поможет нам лучше понять модель объектов.
Например, в имени, которое используется в инструкции def, нет ничего уникального: это всего лишь переменная, которая создается в текущей области видимости, как если бы оно стояло слева от знака =. После того как инструкция def будет выполнена, имя функции представляет собой всего лишь ссылку на объект - ее можно присвоить другим именам и вызывать функцию по любому из них(не только по первоначальному имени):
>>> def echo(message): # Имени echo присваивается объект функции
... print(message)
>>> echo('Прямой вызов') # Вызов объекта по оригинальному имени
Прямой вызов
>>> x = echo # Теперь на эту функцию ссылается еще и имя x
>>> x('Косвенный вызов') # Вызов объекта по другому имени добавлением ()
Косвенный вызов
Поскольку аргументы передаются путем присваивания объектов, функции легко можно передавать другим функциям в виде аргументов. В результате вызываемая функция может вызвать переданную ей функцию простым добавлением списка аргументов в круглых скобках:
>>> def indirect(func, arg):
... func(arg) # Вызов объекта добавлением ()
>>> indirect(echo, 'Вызываем функцию') # Передача функции в функцию
Вызываем функцию
Существует даже возможность наполнять структуры данных функциями, как если бы они были простыми числами или строками. В этом нет ничего необычного, так как составные типы объектов могут содержать объекты любых типов:
>>> lst = [ (echo, 'Тук!'), (echo, 'Тадам!') ]
>>> for (func, arg) in lst:
... func(arg) # Вызов функции, сохраненной в контейнере
...
Тук!
Тадам!
В этом фрагменте просто выполняется обход списка lst и производится вызов функции echo с одним аргументом(обратите внимание на операцию присваивания кортежа в заголовке инструкции цикла for). Важно понять, что функции могут также создаваться и возвращаться другими функциями:
>>> def make(label): # создает функцию, но не вызывает ее
... def echo(message):
... print(label + ' : ' + message)
... return echo
...
>>> F = make('Делай') # Метка сохраняется во вложенной области видимости
>>> F('Тук!') # Вызов функции, созданной функцией make
Делай : Тук!
>>> F('Тадам!') # Вызов функции с другим сообщением но с той же меткой, созданной функцией make
Делай : Тадам!
Универсальность модели объектов в языке Python и отсутствие необходимости объявлять типы переменных обеспечивают функциям невероятную гибкость.