Использовать "импорт модуля" или "из импорта модуля"?
Я пытался найти исчерпывающее руководство о том, что лучше использовать import module
или from module import
. Я только начал с Python и пытаюсь исходить из лучших практик.
В принципе, я надеялся, что кто-нибудь сможет поделиться своим опытом, какие предпочтения есть у других разработчиков и каков наилучший способ избежать каких-либо ошибок в будущем?
Переведено автоматически
Ответ 1
Разница между import module
и from module import foo
в основном субъективна. Выберите тот, который вам больше нравится, и будьте последовательны в его использовании. Вот несколько моментов, которые помогут вам определиться.
import module
- Плюсы:
- Меньше обслуживания ваших
import
инструкций. Не нужно добавлять никаких дополнительных импортов, чтобы начать использовать другой элемент из модуля
- Меньше обслуживания ваших
- Минусы:
- Ввод
module.foo
в вашем коде может быть утомительным и избыточным (скуку можно свести к минимуму, используяimport module as mo
then typingmo.foo
)
- Ввод
from module import foo
- Плюсы:
- Меньше печатать
foo
- Больше контроля над тем, к каким элементам модуля можно получить доступ
- Меньше печатать
- Минусы:
- Чтобы использовать новый элемент из модуля, вам необходимо обновить свой
import
оператор - Вы теряете контекст о
foo
. Например, менее понятно, чтоceil()
делает по сравнению сmath.ceil()
- Чтобы использовать новый элемент из модуля, вам необходимо обновить свой
Любой метод приемлем, но не используйте from module import *
.
Для любого разумно большого набора кода, если вы import *
вы, вероятно, будете цементировать его в модуль, который невозможно удалить. Это связано с тем, что трудно определить, какие элементы, используемые в коде, взяты из 'module', что упрощает переход к точке, когда вы думаете, что import
больше не используете, но в этом чрезвычайно сложно быть уверенным.
Ответ 2
Здесь есть еще одна деталь, не упомянутая, связанная с записью в модуль. Конечно, это может быть не очень распространено, но мне это время от времени требовалось.
Из-за того, как ссылки и привязка имен работают в Python, если вы хотите обновить какой-либо символ в модуле, скажем foo.bar , извне этого модуля, и чтобы другой импортирующий код "видел" это изменение, вы должны импортировать foo определенным способом. Например:
модуль foo:
bar = "apples"
модуль a:
import foo
foo.bar = "oranges" # update bar inside foo module object
модуль b:
import foo
print foo.bar # if executed after a's "foo.bar" assignment, will print "oranges"
Однако, если вы импортируете имена символов вместо имен модулей, это не сработает.
Например, если я сделаю это в модуле a:
from foo import bar
bar = "oranges"
Никакой код за пределами a
не будет отображаться bar
как "оранжевые", потому что моя настройка bar
просто повлияла на имя "bar" внутри модуля a
, оно не "достигло" foo
объекта модуля и не обновило его bar
.
Ответ 3
Хотя многие люди уже объясняли о import
vs import from
, я хочу попытаться объяснить немного больше о том, что происходит под капотом, и где находятся все места, которые он изменяет.
import foo
:
Импортирует foo
и создает ссылку на этот модуль в текущем пространстве имен. Затем вам нужно определить завершенный путь к модулю для доступа к определенному атрибуту или методу изнутри модуля.
Например. foo.bar
но не bar
from foo import bar
:
Импортирует foo
и создает ссылки на все перечисленные элементы (bar
). Не устанавливает переменную foo
.
Например. bar
но не baz
или foo.baz
from foo import *
:
Импортирует foo
и создает ссылки на все общедоступные объекты, определенные этим модулем в текущем пространстве имен (все, что указано в __all__
if __all__
exists, в противном случае все, что не начинается с _
). Не устанавливает переменную foo
.
Например. bar
и baz
, но не _qux
или foo._qux
.
Теперь давайте посмотрим, когда мы это сделаем import X.Y
:
>>> import sys
>>> import os.path
Проверьте sys.modules
с помощью name os
и os.path
:
>>> sys.modules['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> sys.modules['os.path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
Проверьте globals()
и locals()
параметры пространства имен с помощью os
и os.path
:
>>> globals()['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> locals()['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> globals()['os.path']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'os.path'
>>>
Из приведенного выше примера мы обнаружили, что в локальное и глобальное пространства имен вставлено только os
.
Итак, мы должны иметь возможность использовать:
>>> os
<module 'os' from
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> os.path
<module 'posixpath' from
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>>
Но не path
.
>>> path
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined
>>>
Как только вы удалите пространство имен os
from locals() , вы не сможете получить доступ к os
а также к os.path
, даже если они существуют в sys.modules:
>>> del locals()['os']
>>> os
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>> os.path
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>>
Теперь давайте поговорим о import from
:
from
:
>>> import sys
>>> from os import path
Проверьте sys.modules
с помощью os
и os.path
:
>>> sys.modules['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> sys.modules['os.path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
Мы обнаружили, что в sys.modules
мы нашли то же самое, что и раньше, используя import name
Хорошо, давайте проверим, как это выглядит в locals()
и globals()
правилах пространства имен:
>>> globals()['path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> locals()['path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> globals()['os']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'os'
>>>
Вы можете получить доступ, используя name, path
а не byos.path
:
>>> path
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> os.path
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>>
Давайте удалим 'path' из locals()
:
>>> del locals()['path']
>>> path
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined
>>>
Последний пример использования псевдонима:
>>> from os import path as HELL_BOY
>>> locals()['HELL_BOY']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> globals()['HELL_BOY']
<module 'posixpath' from /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>>
И путь не определен:
>>> globals()['path']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'path'
>>>
Ответ 4
Оба способа поддерживаются по определенной причине: бывают случаи, когда один более подходит, чем другой.
import module
: удобно, когда вы используете много битов из модуля. недостатком является то, что вам нужно будет дополнять каждую ссылку именем модуля.from module import ...
: приятно, что импортированные элементы можно использовать напрямую, без префикса имени модуля. Недостатком является то, что вы должны перечислять каждую вещь, которую вы используете, и что в коде неясно, откуда что взялось.
Что использовать, зависит от того, что делает код понятным и читабельным, и имеет более чем малое отношение к личным предпочтениям. Я склоняюсь к import module
в целом, потому что в коде очень ясно, откуда взялся объект или функция. Я использую, from module import ...
когда я часто использую какой-либо объект / функцию в коде.