Понимание приоритета импорта Python
Мне нужно пояснить, как обрабатывается импорт на уровне модуля и класса при сосуществовании в одном пространстве имен. См. следующие примеры:
Работает:
import datetime
print datetime.datetime.utcnow()
Неудача:
from datetime import datetime
print datetime.datetime.utcnow()
Ошибка: AttributeError: тип объекта ' datetime.датавремя' нет атрибут 'datetime'
Работает:
from datetime import datetime # Is this ignored?
import datetime
print datetime.datetime.utcnow()
Что именно происходит в 3-м примере? Заменяет ли импорт второго модуля первый импорт, относящийся к определенному классу? Означает ли это, что импорт модулей и классов не должен смешиваться в одном пространстве имен?
5 ответов:
Нет такого приоритета. Результат определяется порядком выполнения операторов
import
следующим образом.Если вы попытаетесь импортировать несколько объектов с именем
X
в ваше пространство имен, каждый импорт будет повторно привязанX
к тому, что он импортирует.Поэтому в конце это будет последний импорт, который будет действовать в том, что касается имени
X
.Именно это и происходит в вашем третьем примере:
from datetime import datetime # This isn't ignored, but the name is immediately rebound # by the next line import datetime # Rebinds the name
Некоторые IDE, поддерживающие python, дадут вам объяснение, но да, вы переопределяете (перезаписываете, заменяете) импорт в 3-м примере. Каждое имя в файле различно. Если вам нужен доступ к модулю и классу, которые имеют общее имя, вам нужно использовать что-то вроде
from datetime import datetime as dt
.
Импорт-это на самом деле просто назначение: он задает имя в текущем пространстве имен. Итак, в третьем случае вы устанавливаете имя
datetime
равным классу datetime, а затем немедленно переназначаете его модулю datetime.
Нет никаких причин делать это так:
from datetime import datetime print datetime.datetime.utcnow()
Этот код, с другой стороны, будет делать именно то, что вы хотите:
from datetime import datetime print datetime.utcnow()
Ваш первый пример импортирует модуль
datetime
и предоставляет меткуdatetime
в локальном пространстве имен, представляющем его, а затем вызывает методutcnow()
объектаdatetime
, принадлежащего модулюdatetime
. Второй добавляет объектdatetime.datetime
(Не модуль) в локальное пространство имен с меткойdatetime
, но объектdatetime
не имеет атрибутаdatetime
, поэтому вы получаете исключение. В третьем примере объектdatetime.datetime
присваивается метке этого имени в пространстве имен, а затем переназначается метке модуляdatetime
. Таким образом, игнорируя механикуimport
, которая не имеет отношения к этому вопросу (в основном, добавляя модули кsys.modules
, если они еще не существуют), то, что у вас есть, эквивалентно:datetime = sys.modules['datetime'] datetime.datetime.utcnow()
Затем
datetime = sys.modules['datetime'].datetime datetime.datetime.utcnow()
Затем
datetime = sys.modules['datetime'].datetime datetime = sys.modules['datetime'] datetime.datetime.utcnow()