Механика импорта Python - PullRequest
       16

Механика импорта Python

12 голосов
/ 17 декабря 2009

У меня есть два связанных вопроса Python по импорту. Они легко тестируемы, но мне нужны ответы, которые определяются языком и не зависят от реализации, и меня также интересует стиль / соглашение, поэтому я спрашиваю здесь.

1)

Если модуль A импортирует модуль B, а модуль B импортирует модуль C, может ли код в модуле A ссылочный модуль C без явного импорта? Если да, правильно ли я полагаю, что это плохая практика?

2)

Если я импортирую модуль A.B.C, импортирует ли он также модули A и A.B? Если да, то лучше ли явно явным образом import A; import A.B; import A.B.C?

Ответы [ 2 ]

12 голосов
/ 17 декабря 2009

Первое, что вы должны знать, это то, что язык Python НЕ является стандартом ISO. Это несколько отличается от C / C ++, и это означает, что не существует «правильного» способа определения поведения языка - CPython может что-то делать только потому, что он был закодирован таким образом, а Jython может делать наоборот.

о ваших вопросах, помните, что "импорт" модуля - это операция, состоящая из двух частей: сначала модуль загружается - если его никогда не было, например, если он не был доступен в sys.modules, то имя связывается с этим модулем в локальном пространстве имен.

следовательно:

1) Да, вы можете ссылаться на все, что вы хотите от модуля a, предоставляя правильное пространство имен, например, вам придется сделать что-то вроде

B.C.name = "что-то"

И я думаю, что это очень редко делается в программах на Python и может считаться плохой практикой, так как это вызывает «транзитивный переход» - если какая-то реализация модуля B подвергается рефакторингу и больше не зависит от C, она должна продолжать предлагать Модуль C только для удовлетворения Aps.

Конечно, установка __ all __ может предотвратить это, и хорошей практикой может быть помещение __ all __ во все ваши модули и экспорт просто символов, которые вы хотите сделать действительно общедоступными.

2) Да и нет. Doing

import a.b.c.d 

выполняет первый этап импорта (загрузка) для всех модулей, но второй только для a (и, рекурсивно, в b относительно c и т. Д.), Но все модули в цепочке должны быть ссылается на полное пространство имен; после такого импорта можно сделать

a.something
a.b.something
a.b.c.something

но вы не можете сделать

c.something
b.something

Я должен признать, что такое использование довольно редко; Обычно я предпочитаю способ импорта из модуля «что-то импортировать», и, как правило, вы просто спрашиваете, что вам нужно - такое вложение не является обычным явлением в библиотеках, и его использование не столь распространено.

Часто бывают «внешние пакеты», просто используемые для организации, которые содержат модули с классами. Весьма вероятно, что a, b, c выше - это просто пакеты, а d - это модуль, который действительно содержит классы, функции и другие объекты. Таким образом, правильное использование будет:

from a.b.c.d import name1, name2, name3

Надеюсь, это утоляет ваше любопытство.

11 голосов
/ 17 декабря 2009

Алан дал отличный ответ, но я хотел бы добавить, что для вашего вопроса 1 это зависит от того, что вы подразумеваете под «импортом».

Если вы используете синтаксис from C import x, тогда x станет доступным в пространстве имен B. Если в A вы затем выполните import B, вы получите доступ к x с A как B.x.

Это не столько плохая практика, сколько потенциально запутанная, и она усложнит отладку и т. Д., Так как вы не обязательно будете знать, откуда появились объекты.

...