Я был удивлен, узнав, что оба вызова main.py
работают:
import package_top
package_top.module.hello() # I thought this won't work ...
package_top.hello() # I thought this is the only way
package_top
package_top/
├── __init__.py
└── module.py
__init__.py
from .module import hello
module.py
def hello():
print("module_hello")
Насколько я понимаю, когда я вызываю import package_top
в main.py
, он запускает __init__.py
, который добавляет hello в пространство имен package_top, а затем package_top добавляется в пространство имен main, поэтому я могу получить доступ к hello с помощью package_top.hello()
. Чего я не понимаю, так это почему второй вызов тоже работает?
Я ожидаю, что программа выдаст ошибку во второй строке.
Механизм импорта Python изменяет объект модуля package_top
и добавляет атрибут module
как часть импорта дочернего модуля. См. документацию по импорту Python в подмодулях :
Когда подмодуль загружается с использованием любого механизма (например, API-интерфейсов importlib, операторов import или import-from или встроенного
__import__()
), в пространстве имен родительского модуля размещается привязка к объекту подмодуля.
Другие операторы импорта, такие как from other_package import x, y
, только добавляют имена x
и y
к объекту импортирующего модуля. В вашем случае from .module import hello
одновременно импортирует функцию hello
, а также импортирует подмодуль module
из package_top
, поэтому ваш оператор импорта создает как package_top.hello
, так и package_top.module
, что, в свою очередь, дает вам доступ к package_top.module.hello
.
Вы можете подтвердить это, распечатав область действия модуля после импорта:
from .module import hello
print(dir())
принты:
['__builtins__', (more default __stuff__ ...), 'hello', 'module']
Поэтому package_top.module.hello()
работает без проблем. Удалите оператор from .module import hello
, и вы увидите, что подмодуль не импортирован, и оператор package_top.module.hello()
завершится ошибкой.
@jkr, это не имеет значения, печать dir()
в модуле все равно показывает атрибут module
.
Имхо, это странное несоответствие. И остается вопрос, почему модуль так добавляется? Я не понимаю, почему это должно быть так.
Это часть процесса импорта подмодуля Python, я дал ссылку на документацию, в которой это указано.
Спасибо! Отличный ответ! Таким образом, мой результат можно объяснить документом системы импорта. Но я также хочу спросить, почему from top_module import xxx
и from sub_module import xxx
в Python работают по-разному. Почему он установлен так? Несоответствие действительно сбивает с толку.
Привет, Цзычэн Чжан! Я не понимаю, что вы имеете в виду. Не могли бы вы отредактировать свой первоначальный вопрос или открыть новый вопрос, где вы полностью объясните его? Ваш вопрос задан очень хорошо, что помогло мне ответить. С этим комментарием у меня недостаточно информации, чтобы сделать это снова :) спасибо
В противном случае, если вы считаете, что на ваш вопрос есть полный ответ, вы можете «принять» мой ответ, что дает мне дополнительные баллы (ура!) и дает сообществу понять, что им не нужно искать другой ответ.
но ОП не пишет
import .module
, ОП пишетfrom .module import hello