У меня есть такой файл python,
# mod.py
count = 0
def inc():
global count
count = count + 1
В main1.py я импортирую count
вот так, и значение правильное:
import mod
mod.inc()
print(mod.count)
В main2.py я импортирую count
напрямую, оно всегда равно нулю:
import mod
from mod import count
mod.inc()
print(count)
В чем разница?
Вы забыли поставить :
там.
@CoolCloud Можете ли вы привести пример?
Что вы подразумеваете под "и это будет правильное значение". Какова будет ценность?
@CoolCloud обновил вопрос, прикрепил несколько файлов
Вы импортируете count напрямую, поэтому, даже если вы вызываете внутреннюю функцию в модуле, значение, которое импортируется первым, не изменится (на мой взгляд)
from mod import count
создает псевдоним с именем count
текущего значения, связанного с mod.count
в глобальной области видимости модуля импорта. Первоначально оба имени относятся к одному и тому же значению, поэтому для изменяемых типов, если они изменяются на месте (например, присваивание атрибутам, индексам и т. д.), они будут видны из обоих псевдонимов. Но если один из них переназначается (простое name =
присваивание или расширенное присваивание, такое как +=
для неизменяемых типов), связь исчезает; это разные имена, привязанные к одному объекту, и вы привязываете одно из них к совершенно другому объекту.
Когда вы читаете/назначаете mod.count
напрямую, наложение псевдонимов не происходит; есть только одно имя, и все вовлеченные стороны читают и перепривязывают это же имя.
В этом случае main2
создает локальное имя count
, которое ссылается на тот же объект 0
, хранящийся в mod
count
. Затем он вызывает mod.inc
, который перепривязывает count
в mod
, но псевдоним в main2
этого не видит (вы можете запросить счетчик ссылок на CPython и увидеть, что он упал, вот и все); он счастливо остается привязанным к исходному 0
, в то время как mod.count
получил отскок к 1
.
Если это поможет, представьте сценарий в случае без импорта. Если у вас есть:
a = 0
b = a
a = a + 1
вы ожидаете, что b
изменится, чтобы соответствовать a
? Связь между импортом count
в main2
и mod.count
точно такая же, как вы видите здесь; a
(mod.count
) изначально 0
, вы сделали псевдоним для этого значения с именем b
(main2.count
), затем вы сделали a
(mod.count
) что-то еще (1
); b
(main2.count
) не следует изменять в этом сценарии (в языке, где это было, вам нужно добавить какой-то способ отличать ссылки от копий; C++ делает это с int&
против int
, но у Python нет языка- уровень эквивалентен ссылкам на C++).
Пойдем шаг за шагом.
Дело 1
import mod
Здесь у нас есть mod
в памяти. mod.count
— это поле, а mod.inc
— функция. Попытка напечатать count
приведет к ошибке.
mod.inc()
print(mod.count)
Это увеличивает mod.count
, и, таким образом, если мы напечатаем mod.count
, мы получим «правильное» значение.
случай 2
import mod
снова импортируем mod
в нашу память, что означает, что нам разрешено использовать mod.count
и mod.inc
.
from mod import count
Мы импортируем count
в нашу память. Поэтому мы импортировали две переменные, а именно count
и mod.count
. Хотя они импортируются аналогичным образом, теперь они называются двумя отдельными переменными.
mod.inc()
Здесь мы увеличиваем mod.count
, так как это переменная, на которую ссылается mod.inc
.
print(count)
Мы печатаем переменную count, не увеличенную на mod.inc
, и таким образом получаем ноль.
Потому что, когда вы называете
inc
, вы также используетеfrom modules import a
Я думаю,modules
иmodules.a
трактуются по-разному вsys.modules
.