Шаг 36.
Python: тонкости программирования. Эффективные функции. Функции Python - это объекты первого класса. Функции могут быть вложенными

    На этом шаге мы рассмотрим, какие возможности предоставляют вложенные функции.

    Быть может, вы удивитесь, но Python допускает определение функций внутри других функций. Такие функции нередко называются вложенными функциями (nested functions), или внутренними функциями (inner functions). Приведем пример:

>>> def speak(text):
	def whisper(t):
		return t.lower() + '...'
	return whisper(text)

>>> speak('Привет, Мир')
'привет, мир...'

    Итак, что же тут происходит? Всякий раз, когда вы вызываете функцию speak(), она определяет новую внутреннюю функцию whisper() и затем после этого немедленно ее вызывает.

    Правда, вот вам неожиданный поворот - функция whisper() не существует за пределами функции speak():

>>> whisper('Йоу')
Traceback (most recent call last):
NameError: name 'whisper' is not defined
>>> speak.whisper
Traceback (most recent call last):
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:
		return yell
	else:
		return whisper

    Обратите внимание на то, как функция get_speak_func() фактически не вызывает ни одну из своих внутренних функций - она просто выбирает соответствующую внутреннюю функцию на основе аргумента volume и затем возвращает объект-функцию:

>>> get_speak_func(0.3)
<function get_speak_func.<locals>.whisper at 0x0000019E85BEB310>
>>> get_speak_func(0.7)
<function get_speak_func.<locals>.yell at 0x0000019E85BEB4C0>

    Разумеется, вы можете продолжить и вызвать возвращенную функцию непосредственно, либо сначала присвоив ее переменной:

>>> speak_func = get_speak_func(0.7)
>>> speak_func('Привет')
'ПРИВЕТ!'

    Только подумайте... Это означает, что функции не только могут принимать линии поведения через аргументы, но и возвращать линии поведения. Здорово, правда?

    На следующем шаге мы рассмотрим локальное состояние функций.




Предыдущий шаг Содержание Следующий шаг