Вызов функции внутри функции питон

Замыкания в Python

Python позволяет определять функции внутри других функций. «Внутренняя» функция называется вложенной. Вот пример:

def say(): greeting = "Привет" def display(): print(greeting) display()

В этом примере мы объявили функцию display() внутри функции say() . Функция display() — вложенная.

При этом в функции display() используется переменная greeting , которая инициализирована вне этой функции, то есть из нелокальной области видимости.

В Python такие переменные как greeting называются свободными переменными.

На самом деле функция display() состоит из двух частей:

Так вот все вместе это называется замыканием (closure).

Замыкание (closure) — это вложенная функция, которая ссылается на одну или более переменных из объемлющей (enclosing) области видимости.

Можно вернуть функцию из функции

В Python функция может возвращать другую функцию. Например, так:

def say(): greeting = "Привет" def display(): print(greeting) return display 

В этом примере функция say() возвращает функцию display() , а не выполняет ее.

Когда say() возвращает display() , на самом деле возвращается замыкание:

Следующая инструкция присваивает возвращаемое значение функции say() переменной fn . Поскольку fn — это функция, ее можно вызвать:

Функция say() выполняется и возвращает функцию fn() . Когда выполняется fn() , функция say() уже завершила выполнение.

Это значит, что область видимости функции say() уже не существует к тому моменту, когда выполняется fn() .

Поскольку переменная greeting принадлежит области видимости функции say() , она, по идеи, тоже должна уничтожаться после выполнения say() .

Однако fn() все равно как-то выводит значение переменной greeting , как вы видите в примере выше.

Разберемся, как это работает и почему так происходит.

Ячейки и переменные с несколькими областями видимости

Переменная greeting «разделяется» между двумя областями видимости:

То есть greeting находится одновременно в двух областях видимости. Тем не менее, она всегда ссылается на один и тот же строковый объект «Привет» .

Для этого Python создает промежуточный объект — ячейку (cell).

Узнать адрес ячейки в памяти можно через свойство __closure__ , как показано ниже:

__closure__ возвращает кортеж ячеек.

В этом примере адрес ячейки в памяти — 0x0000017184915C40 . Она ссылается на строковый объект по адресу 0x0000017186A829B0 .

Если вы отобразите адрес памяти строкового объекта в функции say() и замыкании, то увидите, что они ссылаются на один и тот же объект в памяти:

def say(): greeting = "Привет" print(hex(id(greeting))) def display(): print(hex(id(greeting))) print(greeting) return display fn = say() fn() 
0x17186a829b0
0x17186a829b0

Когда вы обращаетесь к значению переменной greeting , Python технически дважды «прыгает» в память, чтобы получить значение строки.

Это объясняет, почему когда область видимости функции say() уже не существовала, вы все равно могли обратиться к строковому объекту, на который ссылается переменная greeting .

На основе этого механизма можно определить замыкание по-другому:

Замыкание — это функция и расширенная область видимости, в которой содержатся свободные переменные.

Чтобы узнать, какие свободные переменные содержатся в замыкание, можно использовать __code__.co_freevars . Например:

def say(): greeting = "Привет" def display(): print(greeting) return display fn = say() print(fn.__code__.co_freevars) // Вывод: ('greeting',)

В этом примере fn.__code__.co_freevars вернет переменную greeting — единственную свободную переменную в замыкании fn .

Когда Python сам создает замыкания

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

1. Сначала определим функцию multiplier() , которая возвращает замыкание:

def multiplier(x): def multiply(y): return x * y return multiply

Функция multiplier() возвращает произведение двух аргументов. Но возвращается не само произведение, а замыкание.

2. Теперь вызовем функцию multiplier() три раза:

m1 = multiplier(1) m2 = multiplier(2) m3 = multiplier(3)

Вызовы функция создадут три замыкания. Каждая функция умножает число на 1, 2, и 3 соответсвенно.

3. А теперь выполним функции замыканий:

print(m1(10)) print(m2(10)) print(m3(10))

Как вы видите, у m1 , m2 и m3 разные инстансы замыкания.

Замыкания и цикл for

Предположим, что нам нужно создать все три вышеуказанные замыкания одновременно. Это можно сделать, например, так:

multipliers = [] for x in range(1, 4): multipliers.append(lambda y: x * y) m1, m2, m3 = multipliers print(m1(10)) print(m2(10)) print(m3(10))

Что мы здесь делаем

  1. Объявляем список, в котором будем хранить замыкания.
  2. Используем лямбда-выражение, чтобы создать замыкание, и добавляем его в список на каждой итерации.
  3. «Распоковываем» замыкания из списка и присваиваем их переменным m1 , m2 и m3 соответсвенно.
  4. Передаем значения 10, 20 и 30 в каждое замыкание и выполняем их.

Работает не так, как мы ожидали. Почему?

В цикле for x меняет значения от 1 до 3. Когда цикл завершается, значение x — 3.

Каждый элемент списка — соответсвующее замыкание lambda y: x*y .

Python использует значение x для вычислений каждый раз, когда вы вызываются m1(1) , m2(10) и m3(10) . И поскольку в момент выполнения замыкания x всегда 3, результат всех замыканий одинаковый — 30.

Чтобы исправить эту проблему, нужно объяснить Python, что значение x для вычислений нужно использовать в цикле.

def multiplier(x): def multiply(y): return x * y return multiply multipliers = [] for x in range(1, 4): multipliers.append(multiplier(x)) m1, m2, m3 = multipliers print(m1(10)) print(m2(10)) print(m3(10))

СodeСhick.io — простой и эффективный способ изучения программирования.

2023 © ООО «Алгоритмы и практика»

Источник

Как вызвать функцию в Python?

Как известно, функции — это блоки инструкций, предназначенные для выполнения определенных задач в программировании. Функции позволяют разбивать большие фрагменты кода на более мелкие отрезки или модули. Позже их можно вызывать отовсюду. Это позволяет повторно использовать определенные части программы и избегать повторений. Функции можно определять внутри классов, модулей, вложенных функций и так далее.

Основные особенности функций в Python:

  • Используются чтобы избегать повторений в коде,
  • Используются для разделения кода на мелкие модули
  • Позволяют скрывать код и создавать ясность для понимания модулей,
  • Позволяют повторно использовать код и сохранять память,
  • Код из функции можно выполнить только по ее имени,
  • Простой синтаксис: def имя_функции(параметры): .
  1. Для объявления функции в Python используется ключевое слово def .
  2. Название функции должно начинаться с символа латинского алфавита в любом регистре или нижнего подчеркивания.
  3. В каждой функции есть двоеточие и отступ, после которого записывается сам код программы.
  4. Зарезервированные ключевые слова не могут использоваться в качестве названия функции.
  5. Функция может содержать несколько параметров или не иметь их совсем.

Создание функции в Python

Для создания нужно написать ключевое слово def . Синтаксис следующий:

def function_name(): # логика функции return result # возврат значения

Создадим и вызовем реальную функцию в Python:

Источник

Как создать и использовать вложенные функции в Python

Изучите создание и использование вложенных функций в Python для структурирования кода, инкапсуляции и реализации декораторов.

Вложенные функции, или внутренние функции, являются темой, которую нужно освоить при изучении Python. В этой статье мы разберемся, что такое вложенные функции, как их создавать и использовать, а также приведем примеры кода.

Что такое вложенные функции?

Вложенные функции — это функции, определенные внутри других функций. Они могут быть использованы для повышения структурированности кода, инкапсуляции и реализации декораторов.

Создание вложенных функций

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

def outer_function(): print("Я внешняя функция") def inner_function(): print("Я внутренняя функция") inner_function() outer_function()

В этом примере мы создали внутреннюю функцию inner_function внутри внешней функции outer_function . Затем мы вызвали внутреннюю функцию из внешней функции. В результате вызова outer_function() будет выведено:

Я внешняя функция
Я внутренняя функция

Использование вложенных функций

Вложенные функции могут быть использованы в различных случаях. Например, они могут служить для инкапсуляции кода, который не должен быть доступен извне.

def outer_function(x): def inner_function(y): return x * y return inner_function(x) result = outer_function(5) print(result) # Вывод: 25

В этом примере мы использовали вложенную функцию, чтобы умножить x на y . Внешняя функция возвращает результат вызова внутренней функции. Внутренняя функция недоступна извне, что позволяет инкапсулировать логику.

📘 Важно отметить, что вложенные функции имеют доступ к переменным внешней функции. Это называется замыканием.

Пример использования вложенных функций для реализации декораторов

Декораторы — это способ изменения поведения функций или методов с помощью вложенных функций. Вот пример создания простого декоратора с использованием вложенных функций:

def my_decorator(func): def wrapper(): print("Что-то происходит перед вызовом функции") func() print("Что-то происходит после вызова функции") return wrapper def my_function(): print("Я функция, которую нужно изменить") decorated_function = my_decorator(my_function) decorated_function()

В этом примере мы создали декоратор my_decorator , который принимает функцию func в качестве аргумента. Внутри декоратора мы определили вложенную функцию wrapper , которая вызывает переданную функцию func и добавляет дополнительное поведение до и после вызова. Затем мы применили декоратор к функции my_function и вызвали полученную функцию.

В результате выполнения кода будет выведено:

Что-то происходит перед вызовом функции
Я функция, которую нужно изменить
Что-то происходит после вызова функции

Теперь вы знаете, как создавать и использовать вложенные функции в Python. Эти знания помогут вам структурировать код, инкапсулировать логику и реализовывать декораторы. Продолжайте изучать Python, и вскоре вы станете опытным разработчиком! 🚀

Источник

Читайте также:  Browser with javascript support
Оцените статью