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

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

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

1)

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

2)

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

4b9b3361

Ответ 1

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

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

отсюда:

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

B.C.name = "something"

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

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

2) Да и нет. Выполнение

import a.b.c.d 

выполняет первую фазу импорта (погрузка) на всех модулях, а вторая - только на (и, рекурсивно, в 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

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

Ответ 2

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

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

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