Что такое вложенная функция?
Функции являются одними из «первоклассных граждан» Python, что означает, что функции находятся на том же уровне, что и другие объекты Python, такие как целые числа, строки, модули и т. Д. Их можно создавать и уничтожать динамически, передавать другим функциям, возвращать. как значения и т. д.
Python поддерживает концепцию «вложенной функции» или «внутренней функции», которая представляет собой просто функцию, определенную внутри другой функции. В остальной части статьи мы будем использовать слова «внутренняя функция» и «вложенная функция» как синонимы.
Существуют различные причины, по которым кто-то хотел бы создать функцию внутри другой функции. Внутренняя функция может получить доступ к переменным в пределах области видимости. В этой статье мы исследуем различные аспекты внутренних функций в Python.
Определение внутренней функции
Чтобы определить внутреннюю функцию в Python, мы просто создаем функцию
внутри другой функции, используя ключевое слово def
Вот пример:
def function1(): # outer function
print ("Hello from outer function")
def function2(): # inner function
print ("Hello from inner function")
function2()
function1()
Выход
Hello from outer function
Hello from inner function
В приведенном выше примере function2()
была определена внутри
function1()
, что сделало ее внутренней функцией. Чтобы вызвать
function2()
, мы должны сначала вызвать function1()
. Затем
function1()
продолжит работу и вызовет function2()
как она была
определена внутри нее.
Важно отметить, что внешняя функция должна быть вызвана для выполнения внутренней функции. Если внешняя функция не вызывается, внутренняя функция никогда не будет выполняться. Чтобы продемонстрировать это, измените приведенный выше код на следующий и запустите его:
def function1(): # outer function
print ("Hello from outer function")
def function2(): # inner function
print ("Hello from inner function")
function2()
При выполнении код ничего не вернет!
Вот еще один пример:
def num1(x):
def num2(y):
return x * y
return num2
res = num1(10)
print(res(5))
Выход
50
Код возвращает умножение двух чисел, то есть 10 и 5. Пример показывает, что внутренняя функция может обращаться к переменным, доступным во внешней функции.
До сих пор вы видели, что мы можем получить доступ к переменным внешней функции внутри внутренней функции. Что, если мы попытаемся изменить переменные внешней функции изнутри внутренней функции? Посмотрим, что происходит:
def function1(): # outer function
x = 2 # A variable defined within the outer function
def function2(a): # inner function
# Let's define a new variable within the inner function
# rather than changing the value of x of the outer function
x = 6
print (a+x)
print (x) # to display the value of x of the outer function
function2(3)
function1()
Выход
2
9
Вывод показывает, что мы можем отображать значение переменной,
определенной во внешней функции из внутренней функции, но не изменять
его. Оператор x = 6
помог нам создать новую переменную x
внутри
внутренней функции function2()
а не изменить значение переменной x
определенной во внешней функции function1()
.
В следующем разделе мы обсудим основные причины, по которым мы используем внутренние функции в Python.
Зачем использовать внутренние функции?
Инкапсуляция
Функцию можно создать как внутреннюю функцию, чтобы защитить ее от всего, что происходит вне функции. В этом случае функция будет скрыта от глобальной области видимости. Вот пример:
def outer_function(x):
# Hidden from the outer code
def inner_increment(x):
return x + 2
y = inner_increment(x)
print(x, y)
inner_increment(5)
#outer_function(5)
Выход
Traceback (most recent call last):
File "C:/Users/admin/inner.py", line 7, in <module>
inner_increment(5)
NameError: name 'inner_increment' is not defined
В приведенном выше коде мы пытаемся вызвать inner_increment()
, но
вместо этого получили ошибку.
Теперь закомментируйте вызов inner_increment()
и раскомментируйте
вызов outer_function()
как показано ниже:
def outer_function(x):
# Hidden from the outer code
def inner_increment(x):
return x + 2
y = inner_increment(x)
print(x, y)
#inner_increment(5)
outer_function(5)
Выход
5 7
Приведенный выше сценарий показывает, что внутренняя функция, то есть
inner_increment()
, защищена от того, что происходит за ее пределами,
поскольку на переменную x
внутри inner_increment
не влияет значение,
переданное параметру x
внешней функции. Другими словами, переменные
внутри внутренней функции недоступны вне ее. Такой шаблон дизайна дает
большое преимущество. После проверки всех аргументов во внешней функции
мы можем безопасно пропустить проверку ошибок во внутренней функции.
Замыкания и фабричные функции
Все примеры, которые мы видели до сих пор, содержат обычные функции, которые были вложены в другие функции. Мы можем написать такие функции по-другому, вместо того, чтобы вкладывать их в другие функции. У нас нет конкретной причины, почему мы должны их вкладывать.
Однако в случае замыканий необходимо использовать вложенные функции.
Мы можем связывать / передавать данные в функцию, не обязательно передавая данные в функцию через параметры. Это делается с помощью укупорки. Это функциональный объект, который может запоминать значения в охватывающих областях, даже если они недоступны в памяти. Это означает, что у нас есть закрытие, когда вложенная функция ссылается на значение, которое находится в ее охватывающей области.
Цель замыкания - заставить внутреннюю функцию запоминать состояние своего окружения при вызове, даже если его нет в памяти. Замыкание вызывается внутренней функцией, но не внутренней функцией. Закрытие работает путем закрытия локальной переменной в стеке, которая остается после того, как создание стека завершилось.
Ниже приведены условия, которые необходимо выполнить для создания замыкания в Python:
- Должна быть вложенная функция
- Внутренняя функция должна ссылаться на значение, которое определено во включающей области
- Включающая функция должна возвращать вложенную функцию
Рассмотрим следующий пример:
def function1(name):
def function2():
print('Hello ' + name)
return function2
func = function1('Nicholas')
func()
Выход
Hello Nicholas
Приведенный выше код демонстрирует, что с помощью замыканий мы можем
сгенерировать и вызвать функцию из-за пределов ее области посредством
передачи функции. Объем function2()
находится только внутри
function1()
. Однако с помощью замыканий у нас появилась возможность
расширить эту область видимости и вызвать ее извне.
Внутренние функции помогают нам определять фабричные функции . Заводская функция - это функция, которая создает другой объект. Например:
def power_generator(num):
# Create the inner function
def power_n(power):
return num ** power
return power_n
power_two = power_generator(2)
power_three = power_generator(3)
print(power_two(8))
print(power_three(4))
Выход
256
81
В приведенном выше скрипте из функции power_n(power)
мы создали два
других объекта, power_two
и power_three
. Это делает
power_n(power)
фабричной функцией, поскольку она генерирует
power_two
и power_three
, используя передаваемый нами параметр.
Заключение
Внутренняя функция - это просто функция, которая определена внутри другой функции. Внутренняя функция может получить доступ к переменным, которые были определены в рамках внешней функции, но не может их изменить. Существует ряд причин, по которым нам может потребоваться создать внутреннюю функцию. Например, внутренняя функция защищена от того, что происходит вне ее. Внутренние функции также являются хорошим способом создания замыканий в Python.