Ответ 1
Часть 1
Модуль загружается только один раз, поэтому нет потери производительности, импортируя его снова. Если вы действительно хотели, чтобы он снова загружался/разбирался, вам нужно было бы reload()
модуля.
Первое место отмечено
sys.modules
, кешем всех модулей, которые были импортированы ранее. [источник]
Часть 2
from foo import *
импортирует a
в локальную область. При присвоении значения a
оно заменяется новым значением - но исходная переменная foo.a
не затрагивается.
Итак, если вы не import foo
и не измените foo.a
, оба вызова вернут одно и то же значение.
Для изменяемого типа, такого как список или dict, это будет другим, изменение его действительно повлияет на исходную переменную - но присвоение ему нового значения все равно не изменит foo.whatever
.
Если вы хотите получить более подробную информацию, посмотрите http://docs.python.org/reference/executionmodel.html:
Следующие конструкции связывают имена: формальные параметры для функций, операторы импорта, определения классов и функций (они связывают имя класса или функции в определяющем блоке) и целевые объекты, которые являются идентификаторами если встречается в присваивании, для заголовка цикла, во второй позиции заголовка исключения или после того, как в инструкции с.
Два жирных раздела являются для вас релевантными: сначала имя a
привязывается к значению foo.a
во время импорта. Затем при выполнении a = 5
имя a
привязано к 5
. Поскольку изменение списка /dict не вызывает привязки, эти операции будут изменять исходный (b
и foo.b
привязаны к тому же объекту, на котором вы работаете). Присвоение нового объекта b
снова будет операция привязки и, следовательно, отделяет b
от foo.b
.
Также стоит отметить, что именно делает оператор import
:
-
import foo
связывает имя модуля с объектом модуля в текущей области, поэтому, если вы изменитеfoo.whatever
, вы будете работать с именем в этом модуле - любые изменения/назначения будут влиять на переменную в модуле. -
from foo import bar
связывает только указанные имена (т.е.foo
останется несвязанным) с элементом с тем же именем вfoo
- поэтому операции надbar
ведут себя так, как описано ранее. -
from foo import *
ведет себя как предыдущий, но импортирует все глобальные имена, которые не имеют префикса с подчеркиванием. Если модуль определяет__all__
, импортируются только имена внутри этой последовательности.
Часть 3 (что даже не существует в вашем вопросе: p)
Документация на python чрезвычайно хороша и обычно многословна - вы найдете ответ на почти все возможные вопросы, связанные с языком. Вот несколько полезных ссылок:
- http://docs.python.org/reference/datamodel.html (классы, свойства, магические методы и т.д.)()
- http://docs.python.org/reference/executionmodel.html (как работают переменные в python)
- http://docs.python.org/reference/expressions.html
- http://docs.python.org/reference/simple_stmts.html (такие выражения, как
import
,yield
) - http://docs.python.org/reference/compound_stmts.html (операторы блока, такие как
for
,try
,with
)