'ПРИВЕТИЩЕ!'
Функции могут передаваться другим функциям
Поскольку функции являются объектами, их можно передавать в качестве
аргументов другим функциям. Вот функция
greet
, которая форматирует
строковое значение приветствия, используя переданный в нее объект-
функцию, и затем его печатает:
def greet(func):
greeting = func('Привет! Я — программа Python')
print(greeting)
На результирующее приветствие можно влиять, передавая различные
функции. Ниже показано, что происходит, если в функцию
greet
пере-
дать функцию
bark
:
>>> greet(bark)
'ПРИВЕТ! Я — ПРОГРАММА PYTHON'
Разумеется, можно также определить новую функцию, чтобы сгенериро-
вать приветствие с другим колоритом. Например, следующая функция
whisper
может сработать лучше, если вы не хотите, чтобы ваши програм-
мы Python походили на Оптимуса Прайма из мультсериалов:
70 Глава 3 • Эффективные функции
def whisper(text):
return text.lower() + '...'
>>> greet(whisper)
'Привет! Я — программа Python...'
Способность передавать объекты-функции в другие функции в качестве
аргументов имеет мощные последствия. Она позволяет в своих програм-
мах абстрагироваться и раздавать поведение. В этом примере функция
greet
остается прежней, но вы можете влиять на ее результат, передавая
различные линии поведения приветствия.
Функции, которые в качестве аргументов могут принимать другие функ-
ции, также называются функциями более высокого порядка (higher-order
functions). Они являются непременным условием функционального стиля
программирования.
Классическим примером функций более высокого порядка в Python
является встроенная функция
map
. Она принимает объект-функцию
и итерируемый объект и затем вызывает эту функцию с каждым эле-
ментом итерируемого объекта, выдавая результат по мере прохождения
итерируемого объекта.
Ниже показано, как вы могли бы отформатировать всю последователь-
ность приветствий сразу, применив к ним функцию
bark
:
>>> list(map(bark, ['здравствуй', 'эй', 'привет']))
['ЗДРАВСТВУЙ!', 'ЭЙ!', 'ПРИВЕТ!']
Как видите, функция более высокого порядка
map
обошла весь список
и применила функцию
bark
к каждому его элементу. В результате у нас
теперь новый объект-список с измененными приветственными строко-
выми значениями.
Функции могут быть вложенными
Быть может, вы удивитесь, но Python допускает определение функций
внутри других функций. Такие функции нередко называются вложен-
ными функциями (nested functions), или внутренними функциями (inner
functions). Приведем пример:
3 .1 . Функции Python — это объекты первого класса 71
def speak(text):
def whisper(t):
return t.lower() + '...'
return whisper(text)
>>> speak('Привет, Мир')
'привет, мир...'
Итак, что же тут происходит? Всякий раз, когда вы вызываете функцию
speak
, она определяет новую внутреннюю функцию
whisper
и затем
после этого немедленно ее вызывает. В этом месте мой мозг начинает
испытывать легкий зуд, но в целом пока материал относительно после-
довательный.
Правда, вот вам неожиданный поворот — функция
whisper
не существует
за пределами функции
speak
:
>>> whisper('Йоу')
NameError:
"name 'whisper' is not defined"
>>> speak.whisper
AttributeError:
"'function' object has no attribute 'whisper'"
Но что, если вы действительно хотите получить доступ к этой вложенной
функции
whisper
за пределами функции
speak
? Не забывайте, функции
являются объектами — и вы можете вернуть внутреннюю функцию ис-
точнику вызова родительской функции.
Например, ниже приведена функция, определяющая две внутренние
функции. В зависимости от аргумента, передаваемого в функцию верхнего
уровня, она выбирает и возвращает источнику вызова одну из внутренних
функций:
def get_speak_func(volume):
def whisper(text):
return text.lower() + '...'
def yell(text):
return text.upper() + '!'
if volume > 0.5:
72 Глава 3 • Эффективные функции
return yell
else:
return whisper
Обратите внимание на то, как функция
get_speak_func
фактически не
Do'stlaringiz bilan baham: |