Подтверждение разницы между импортом * и импортом xxx * - PullRequest
12 голосов
/ 14 декабря 2010

Я был удивлен, узнав, что

import foo

и

from foo import *

по-разному влияют на участников из разных стран.Я хотел подтвердить, что мои эксперименты - правильное поведение.

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

Мне нужно иметь доступ к файлу foo.x из всех файлов, иметь возможность изменять его из всех файлов и отражать это изменение во всех файлах (если хотите, истинно глобально).

Ответы [ 2 ]

15 голосов
/ 14 декабря 2010

Да, ваши наблюдения верны.Это является следствием того, как привязка работает в 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

Тогда это изменение будет распространено на другие импортирующие модули, поскольку один не перезаписывает глобальная ссылка, но следующая , чтобы изменить атрибут объекта, на который она указывает.По сути, вы должны иметь возможность изменять изменяемые объекты, если вы не перезаписываете глобальную привязку.

Я думаю, что что-то вроде этого является наиболее близким к тому, что вы сможете чисто добраться додействительно глобальный в питоне.Как язык, он очень ценит пространства имен.

4 голосов
/ 14 декабря 2010

Учитывая, что глобальные переменные обычно считаются плохими, я подозреваю, что "истинно глобальные" переменные были бы чрезвычайно плохими.

Еще один способ получить похожее поведение - использовать атрибуты класса в одноэлементном объекте и просто импортировать его. Тогда станет понятнее, откуда вы получаете «глобальную» переменную.

...