Что именно импортирует * import *? - PullRequest
44 голосов
/ 02 марта 2010

В Python, что именно импортирует import *? Импортирует ли __init__.py найденную папку?

Например, нужно ли объявлять from project.model import __init__ или достаточно from project.model import *? 1007 *

Ответы [ 6 ]

50 голосов
/ 02 марта 2010

«Преимущество» from xyz import * по сравнению с другими формами импорта заключается в том, что он импортирует все (ну, почти ... [см. (А) ниже] все)) из назначенного модуля под текущий модуль. Это позволяет использовать различные объекты (переменные, классы, методы ...) из импортированного модуля без добавления префикса к имени модуля . Например

>>> from math import *
>>>pi
3.141592653589793
>>>sin(pi/2)
>>>1.0

Эта практика (импорта * в текущее пространство имен), однако, не рекомендуется , потому что она

  • предоставляет возможность для коллизий пространства имен (скажем, если у вас было имя переменной pi до импорта)
  • может быть неэффективным, если количество импортируемых объектов велико
  • явно не документирует происхождение переменной / метода / класса (хорошо иметь эту «самодокументирование» программы для будущего посещения кода)

Как правило, поэтому мы ограничиваем эту практику импорта специальными тестами и т.п. Как указывает @ Denilson-Sá-Maia, некоторые библиотеки, такие как (например, pygame), имеют субмодуль, в котором определены все наиболее часто используемые константы и функции, и такие субмодули эффективно предназначены для импортироваться с import *. Кроме этих специальных субмодулей, в противном случае предпочтительнее ...:

явно импортировать только несколько объектов

>>>from math import pi
>>>pi
>>>3.141592653589793
>>> sin(pi/2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'sin' is not defined

или импортировать модуль в собственное пространство имен (или его псевдоним, в частности, если это длинное имя, и программа ссылается на его объекты много раз)

  >>>import math
  >>>math.pi
  >>>3.141592653589793
  etc..


  >>>import math as m  #bad example math being so short and standard...
  >>>m.pi
  >>>3.141592653589793
  etc..

См. Python документацию по этой теме

(a) В частности, что импортируется с from xyz import *?
если модуль xyz определяет переменную __all__, он импортирует все имена, определенные в этой последовательности, в противном случае он импортирует все имена, кроме тех, которые начинаются со знака подчеркивания.

Примечание Во многих библиотеках есть подмодулей . Например, стандартная библиотека urllib включает подмодули, такие как urllib.request, urllib.errors, urllib.response и т. Д. Общая путаница заключается в том, что

from urllib import *

импортирует все эти подмодули. Это НЕ так : нужно явно импортировать их отдельно, скажем, с from urllib.request import * и т. Д. Это, кстати, не относится к import *, обычный import также не будет импортировать подмодули ( но, конечно, *, который часто является сокращением для "всего" , может ввести в заблуждение людей, полагая, что все подмодули и все остальное будет импортировано).

11 голосов
/ 02 марта 2010

Импортирует (в текущее пространство имен) любые имена, перечисленные модулем (или пакетом) в своем атрибуте __all__ - при отсутствии такого атрибута все имена, которые не начинаются с _.

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

Моя рекомендация, согласно Руководству по стилю Google Python , заключается в том, чтобы всегда импортировать modules , , а не классы или функции (или другие имена) из модулей. Строгое следование этому обеспечивает ясность и точность и позволяет избежать тонких ловушек, которые могут возникать при импорте «материала из модуля».

Импорт пакета (или чего-либо из него) по своей природе загружает и выполняет __init__.py пакета - этот файл определяет тело пакета. Однако оно не связывает имя __init__ в вашем текущем пространстве имен (поэтому в этом смысле оно не импортирует это имя).

4 голосов
/ 02 марта 2010

Да, это так. Он импортирует все (это не приватная переменная, т.е. переменные, имена которых начинаются с _ или __), и вы должны стараться не использовать их в соответствии с " Правильно импортирующими модулями в Python", чтобы избежать загрязнения локального пространства имен.

Этого достаточно, но обычно вы должны либо сделать import project.model, который уже импортирует __init__.py, для " Понимание импорта Python ", но может стать слишком многословным, если вы его слишком много используете, или import project.model as pm или import project.model as model для последующего сохранения нескольких нажатий клавиш при его использовании.

Следуйте советам Алекса в " Что именно импортирует" import * "? "

3 голосов
/ 02 марта 2010

Если project.model - пакет, модуль, на который указывает import project.model, относится к .../project/model/__init__.py. from project.model import * сбрасывает все из пространства имен __init__.py в ваше. Он не делает ничего автоматически с другими модулями в модели. Предпочтительный стиль для __init__.py не содержит ничего.

Никогда и никогда не используйте import *. Это делает ваш код нечитаемым и не поддерживаемым.

2 голосов
/ 01 марта 2019

Вот хороший способ узнать, что звезда / звездочка (*) импортировала из модуля:

before = dir()
from math import *
after = dir()
print(set(after) - set(before))

возвращает:

{'modf', 'pow', 'erfc', 'copysign', 'sqrt', 'atan2', 'e', 'tanh', 'pi', 'factorial', 'cosh', 'expm1', 'cos', 'fmod', 'frexp', 'log', 'acosh', 'sinh', 'floor', 'isclose', 'lgamma', 'ceil', 'gcd', 'ldexp', 'hypot', 'radians', 'atan', 'isnan', 'atanh', 'before', 'isinf', 'fabs', 'isfinite', 'log10', 'nan', 'tau', 'acos', 'gamma', 'asin', 'log2', 'tan', 'degrees', 'asinh', 'erf', 'fsum', 'inf', 'exp', 'sin', 'trunc', 'log1p'}

Я работал с собственным модулемЯ импортировал все явно, но список товаров для импорта становился слишком длинным.Таким образом, пришлось использовать этот метод, чтобы получить список того, что * было импортировано.

2 голосов
/ 02 марта 2010

Если рассматриваемый модуль (project.model в вашем случае) определил список строк с именем __all__, то каждая именованная переменная в этом списке импортируется. Если такой переменной нет, она импортирует все.

...