2010-12-14 1 views
10

я с удивлением обнаружил, чтоПодтверждая разницу между импортом * и от ххх импорта *

import foo 

и

from foo import * 

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

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

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

ответ

14

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

+0

Ничего себе, я не знал этого. Хороший ответ. – invert

4

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

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

+0

Это хороший момент, спасибо за ваш ответ. –

 Смежные вопросы

  • Нет связанных вопросов^_^