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: