Подтвердить что ты не робот

Как точно работает импорт Python?

У меня есть две конкретные ситуации, когда я не понимаю, как импортирование работает в Python:

1-я конкретная ситуация:

Когда я импортирую тот же модуль в двух разных сценариях Python, модуль не импортируется дважды, не так ли? В первый раз, когда Python сталкивается с ним, он импортируется и второй раз проверяет, был ли импортирован модуль или он сделал копию?

2-я конкретная ситуация:

Рассмотрим следующий модуль, называемый bla.py:

a = 10

И тогда у нас есть foo.py, модуль, который импортирует bla.py:

from bla import *

def Stuff ():
    return a

И после этого у нас есть script, называемый bar.py, который выполняется пользователем:

from foo import *
Stuff() #This should return 10 
a = 5
Stuff()

Здесь я не знаю: возвращает ли Stuff() 10 или 5?

4b9b3361

Ответ 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 чрезвычайно хороша и обычно многословна - вы найдете ответ на почти все возможные вопросы, связанные с языком. Вот несколько полезных ссылок:

Ответ 2

Чтобы ответить на свой первый вопрос:

Нет, python не получает "импорт" дважды. Когда python загружает модуль, он проверяет модуль в sys.modules. Если он там отсутствует, он помещается туда и загружается.

Чтобы ответить на второй вопрос:

Модули могут определять, какие имена они будут экспортировать в сценарий from camelot import *, а поведение - создавать имена для существующих значений, а не ссылаться на существующие переменные (у python нет ссылок).

В некоторой смежной теме выполнение from camelot import * не совпадает с обычным импортом.