Как получить доступ к измененной глобальной переменной в init.py в другой модуль? - PullRequest
0 голосов
/ 11 декабря 2019

Я ищу pythonic способ доступа к глобальной переменной (profit_benchmark), которая определена в файле __init__.py, и ее значение изменено в одном из модулей (routines.py), и теперь я хотел получить доступ к profit_benchmark с измененнымзначение в другом модуле (network.py)

Вот структура моей папки:

enter image description here

__ init __. py

profit_benchmark = 50

routines.py

from so import profit_benchmark
profit_benchmark = 60

network.py

from so import profit_benchmark
print(profit_benchmark)

Вывод:

50

Я ожидаю выводаиз 60, потому что переменная profit_benchmark изменена в рутинной.py

Мой вопрос: как я могу получить доступ к новому значению переменной profit_benchmark в network.py, чтобы выходной сигнал был 60

1 Ответ

2 голосов
/ 11 декабря 2019

Первое: Python не имеет реальных глобалов, только глобалы уровня модуля - каждый модуль является отдельным пространством имен, а глобальный является только «глобальным» для модуля, в котором он определен.

Второе:оператор import не похож на C или PHP include - он не «копирует» весь импортируемый модуль в импортирующий, но загружает импортированный модуль (если он еще не был загружен) и создает егодоступно в импортируемом пространстве имен

На самом деле это:

import so

- это сокращение для

from importlib import importmodule
so = importmodule("so")

и это:

from so import profit_benchmark

- этоярлык для

from importlib import importmodule
so = importmodule("so")
profit_benchmark = so.profit_benchmark
del so

Как кратко пояснил Джуанпа, во втором случае происходит то, что вы получаете два имени (so.profit_benchmark и your_importing_module.profit_benchmark), оба из которых указывают на один и тот же объект.

Теперь переменные Python не являются ячейкой памяти в стиле C, они представляют собой записи name => объекта в пространстве имен (в основном, пары ключ: значение в dict). На самом деле присваивание просто делает назначенную именованную точку другим объектом, поэтому при выполнении

from so import profit_benchmark
profit_benchmark = 42

первый оператор создает имя "profit_benchmark" в текущем пространстве имен и связывает его с тем жеобъект как то, на что указывает so.profit_benchmark, а второй оператор связывает текущее пространство имен profit_benchmark name с объектом 42 int, , оставляя so.profit_benchmark полностью неизменным . Все это (и многое другое очень полезное для понимания) подробно объясняется в этой статье Неда Батчелдера .

С другой стороны, когда вы делаете

import so
so.profit_benchmark = 42

имя, которое вы привязываете, фактически so 'global' profit_benchmark - которое фактически стало атрибутом объекта модуля so (во время выполнения модули тоже являются объектами), поэтому любой другой модуль читает so.profit_benchmark теперь получит обновленное значение.

Как говорится : вы попросили "pythonic way", и pythonic способ на самом деле избежать изменяемого глобального состояния в максимально возможной степени (иэто одна из причин, почему "глобалы" в Python не являются действительно глобальными). И дело в том, что как только вы привыкнете использовать как можно больше чистых функций и классов, когда вам нужно иметь общее состояние some для состояния функций, вы понимаете, что можете писать очень большие программы безодин «доступный для записи» глобальный объект (nb: глобалы, предназначенные только для чтения, конечно, в порядке, проблемы начинаются, когда вы начинаете мутировать или, что еще хуже, повторно связывать глобалы).

Итак, вопрос: почему вы думаетевам вообще нужен глобальный доступный для записи? Есть много способов их избежать, но «правильное» решение (я) зависит от конкретного варианта использования, о котором вы ничего не говорите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...