Я новичок в Python, и у меня есть сомнения по поводу того, как объекты модуля связаны с пространством имен пакета __init__.py
.
Я изложу проблему более четко с некоторым кодом.
Предположим, есть пакет с именем myPkg
, содержащий два модуля: firstMod
и secondMod
:
myPkg\
__init__.py
firstMod.py
secondMod.py
Файл __init__.py
имеет следующий вид:
def myFun():
from . import firstMod as fm
myFun()
Файл firstMod
пуст.
Файл secondMod
имеет следующий вид:
def myFun():
from . import firstMod as fm
myFun()
Теперь запустите интерпретатор Python 2.7.15 в том же каталоге, что и myPkg
, и выполните следующие действия:
>>> import myPkg
>>> dir(myPkg)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', 'firstMod', 'myFun']
>>> from myPkg import secondMod
>>> dir(secondMod)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'myFun']
>>>
Хотя ожидался результат dir(secondMod)
, результат dir(myPkg)
оказался неожиданным (для меня). Кажется, что только для модуля __init__.py
пакета имена импортированных объектов модуля связаны с глобальным пространством имен, даже если модули импортируются из функции. Это не происходит в других модулях.
Редактировать: как выясняется, это происходит только при импорте модулей пакета. Импорт внешних модулей из myFun
не приводит к привязке имени в __init__.py
.
Может кто-нибудь объяснить, почему это происходит?
А также: есть ли способ избежать этого поведения?
Редактировать
Обратите внимание, что наличие 'firstMod'
в глобальном пространстве имен __init__.py
является свойством, которое применяется только к пакетам.
На самом деле, если один определяет два модуля:
zeroMod.py
firstMod.py
вне любой упаковки и заполняет zeroMod.py
:
def myFun():
import firstMod as fm
myFun()
интерпретатор не будет привязывать имя 'firstMod'
к глобальному пространству имен zeroMod.py
, даже если firstMod.py
загружается впервые:
>>> import zeroMod
>>> dir(zeroMod)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'myFun']
>>>
Я не понимаю, почему привязка имени происходит для __init__.py
, но не для zeroMod.py
.