Как в функции сослаться на переменную другой функции?
Python 3. PyQt4
Условная модель вопроса:
Есть функция «аа» с переменными. Я хочу в функции «bb» использовать эти переменные вот так:
Обе функции принадлежат классу QWidget.
В реале мой вопрос выглядит так:
Т.е. во второй функции надо воспользоваться переменной из первой функции — кат_index
- Вопрос задан более трёх лет назад
- 2088 просмотров
Оценить 6 комментариев
- Вконтакте
кириллица в имени переменной





В такой форме — никак.
Переменные, объявленные внутри функции, существуют только для этой функции и только на время её выполнения.
Соответственно, нужно либо объявление переменных вынести за пределы функции — в какое-то пространство имён, общее для обеих функций. Либо возвращать переменные в качестве результата функции, и вызывать эту функцию, чтобы получить её результат.
Замыкания в Python
Python позволяет определять функции внутри других функций. «Внутренняя» функция называется вложенной. Вот пример:
В этом примере мы объявили функцию display() внутри функции say() . Функция display() — вложенная.
При этом в функции display() используется переменная greeting , которая инициализирована вне этой функции, то есть из нелокальной области видимости.
В Python такие переменные как greeting называются свободными переменными.
На самом деле функция display() состоит из двух частей:
- Сама функция display() .
- Переменная greeting , в которой содержится значение «Привет» .
Так вот все вместе это называется замыканием (closure).
Замыкание (closure) — это вложенная функция, которая ссылается на одну или более переменных из объемлющей (enclosing) области видимости.
Можно вернуть функцию из функции
В Python функция может возвращать другую функцию. Например, так:
В этом примере функция say() возвращает функцию display() , а не выполняет ее.
Когда say() возвращает display() , на самом деле возвращается замыкание:
Следующая инструкция присваивает возвращаемое значение функции say() переменной fn . Поскольку fn — это функция, ее можно вызвать:
Функция say() выполняется и возвращает функцию fn() . Когда выполняется fn() , функция say() уже завершила выполнение.
Это значит, что область видимости функции say() уже не существует к тому моменту, когда выполняется fn() .
Поскольку переменная greeting принадлежит области видимости функции say() , она, по идеи, тоже должна уничтожаться после выполнения say() .
Однако fn() все равно как-то выводит значение переменной greeting , как вы видите в примере выше.
Разберемся, как это работает и почему так происходит.
Ячейки и переменные с несколькими областями видимости
Переменная greeting «разделяется» между двумя областями видимости:
- Функции say() .
- Замыкания.
То есть greeting находится одновременно в двух областях видимости. Тем не менее, она всегда ссылается на один и тот же строковый объект «Привет» .
Для этого Python создает промежуточный объект — ячейку (cell).
Узнать адрес ячейки в памяти можно через свойство __closure__ , как показано ниже:
Вывод
__closure__ возвращает кортеж ячеек.
В этом примере адрес ячейки в памяти — 0x0000017184915C40 . Она ссылается на строковый объект по адресу 0x0000017186A829B0 .
Если вы отобразите адрес памяти строкового объекта в функции say() и замыкании, то увидите, что они ссылаются на один и тот же объект в памяти:
Вывод
Когда вы обращаетесь к значению переменной greeting , Python технически дважды «прыгает» в память, чтобы получить значение строки.
Это объясняет, почему когда область видимости функции say() уже не существовала, вы все равно могли обратиться к строковому объекту, на который ссылается переменная greeting .
На основе этого механизма можно определить замыкание по-другому:
Замыкание — это функция и расширенная область видимости, в которой содержатся свободные переменные.
Чтобы узнать, какие свободные переменные содержатся в замыкание, можно использовать __code__.co_freevars . Например:
В этом примере fn.__code__.co_freevars вернет переменную greeting — единственную свободную переменную в замыкании fn .
Когда Python сам создает замыкания
Python создает новую область видимости каждый раз, когда выполняется функция. Если функция создает замыкание, Python тоже создаст новое замыкание. Рассмотрите следующий пример:
1. Сначала определим функцию multiplier() , которая возвращает замыкание:
Функция multiplier() возвращает произведение двух аргументов. Но возвращается не само произведение, а замыкание.
2. Теперь вызовем функцию multiplier() три раза:
Вызовы функция создадут три замыкания. Каждая функция умножает число на 1, 2, и 3 соответсвенно.
3. А теперь выполним функции замыканий:
Вывод
Как вы видите, у m1 , m2 и m3 разные инстансы замыкания.
Замыкания и цикл for
Предположим, что нам нужно создать все три вышеуказанные замыкания одновременно. Это можно сделать, например, так:
Что мы здесь делаем
- Объявляем список, в котором будем хранить замыкания.
- Используем лямбда-выражение, чтобы создать замыкание, и добавляем его в список на каждой итерации.
- «Распоковываем» замыкания из списка и присваиваем их переменным m1 , m2 и m3 соответсвенно.
- Передаем значения 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 для вычислений нужно использовать в цикле.
Как обратиться к переменной из другого модуля в PYTHON 3
Мне надо завести в main переменную, которую я смогу изменять в sub. Проблема в том, что sub импортируется в main и при добавлении строчки from main import charts (где charts — нужная мне константа) получается ошибка, как я понимаю, связанная с зацикленным импортом.
Я видел похожий вопрос тут Импорт функций из другого файла pytnon, но там всего лишь один ответ, который мне кажется неправильным. Хотелось бы узнать, существуют ли какие-то еще варианты выхода из данной ситуации
main.py
sub.py
Ответы (2 шт):
main.py
sub.py
1) Можно создать глобальную переменную
2) Можно создать используя @property и .setter, и сразу при обновлении переменной выполнять метод
Как обратиться к переменной из другой функции python
В Python функция фактически представляет отдельный тип. Так мы можем присвоить переменной какую-нибудь функцию и затем, используя переменную, вызывать данную функцию. Например:
В данном случае переменной message присваивается одна из функций. Сначала ей передается функция say_hello() :
После этого переменная message будет указывать на данную функцию, то есть фактически представлять функцию say_hello. А это значит, что мы можем вызывать переменную message как обычную функцию:
Фактически это приведет к выполнению функции say_hello, и на консоль будет выведена строка «Hello». Затем подобным образом мы можем передать переменной message другую функцию и вызвать ее.
Подобным образом можно через переменную вызывать функцию с параметрами и возвращать ее результат:
Функция как параметр функции
Поскольку функция в Python может представлять такое же значение как строка или число, соответственно мы можем передать ее в качестве параметра в другую функцию. Например, определим функцию, которая выводит на консоль результат некоторой операции:
В данном случае функция do_operation имеет три параметра, причем третий параметр, как предполагается, будет представлять функцию, которая принимает два параметра и возвращает некоторый результат. Иными словами третий параметр — operation представляет некоторую операцию, но на момент определения функции do_operation мы точно не знаем, что это будет за операция. Мы только знаем, что она принимает два параметр и возвращает какой-то результат, который потом выводится на консоль.
При вызове функции do_operation мы сможем передать в качестве третьего параметра другую функцию, например, функцию sum:
То есть в данном случае параметр operation фактически будет представлять функцию sum и будет возвращать сумму дву чисел.
Затем аналогичным образов в вызов функции do_operation можно передать третьему параметру другую функцию — multiply, которая выполнит умножение чисел:
Таким образом, более гибкие по функциональности функции, которые через параметры принимают другие функции.
Функция как результат функции
Также одна функция в Python может возвращать другую функцию. Например, определим функцию, которая в зависимости от значения параметра возвращает ту или иную операцию:
В данном случае функция select_operation в зависимости от значения параметра choice возвращает одну из трех функций — sum, subtract и multiply. Затем мы мы можем получить результат функции select_operation в переменную operation:
Так, в данном случае в функцию select_operation передается число 1, соответственно она будет возвращать функцию sum. Поэтому переменная operation фактически будет указывать на функцию sum, которая выполняет сложение двух чисел: