Я был удивлен, узнав, что
import foo
и
from foo import *
имели разные последствия для глобальных участников. Я хотел подтвердить, что мои эксперименты - правильное поведение.
В первом примере изменение члена в модуле foo будет отражать весь код, который импортирует foo. Однако изменение этого элемента в более позднем случае, по-видимому, влияет на файл, в который он был импортирован. Другими словами, использование более позднего подхода даст каждому импортирующему файлу собственную копию членов из foo.
поведение, которое я хочу, - иметь доступ к foo.x из всех файлов, иметь возможность изменять его из всех файлов и отражать это изменение во всех файлах (если это действительно так).
Ответ 1
Да, ваши наблюдения верны. Это является следствием того, как связывание работает в Python.
Когда вы делаете
import foo
тогда foo
становится глобальным именем, которое ссылается на модуль foo
. Когда вы делаете
foo.bar = 7
Затем выполняется ссылка и загружается объект foo
. Затем 7
сохраняется в атрибуте bar
.
Когда другой модуль импортирует foo
, он просто вытаскивает объект из sys.modules['foo']
и получает измененное значение.
Когда вы делаете
from foo import bar
globals()['bar']
устанавливается в качестве ссылки foo.bar
. Когда один из них делает
bar = 7
globals()['bar']
больше не ссылается на foo.bar
, а ссылается на копию 7
. То есть первоначальная привязка в глобальной области модуля импорта просто заменяется.
В первом примере один из них модифицирует атрибуты объекта, который хранится в sys.modules
, и будет общим для всех модулей, которые его импортировали. Во втором примере изменяется глобальная область модуля импорта.
Если бы кто-то делал что-то по строкам
from foo import fobaz
fobaz.foobar = 7
Затем это изменение будет распространено на другие модули импорта, потому что одно не переписывает глобальную ссылку, а следует за ней, чтобы изменить атрибут объекта, на который он указывает. По существу, вы должны иметь возможность изменять изменяемые объекты, пока вы не перезаписываете глобальную привязку.
Я думаю, что что-то вроде этого самое близкое, что вы сможете полностью перейти к истинному глобальному в python. В качестве языка он значительно присваивает пространствам имен.
Ответ 2
Учитывая, что глобальные переменные обычно считаются плохими, я подозреваю, что "истинная глобальная" переменная была бы очень плохой.
Другим способом получения аналогичного поведения является использование атрибутов class-scope в одноэлементном объекте и просто импорт. Тогда становится понятнее, откуда вы получаете глобальную переменную.