Вопрос-Ответ

Use 'import module' or 'from module import'?

Использовать "импорт модуля" или "из импорта модуля"?

Я пытался найти исчерпывающее руководство о том, что лучше использовать import module или from module import. Я только начал с Python и пытаюсь исходить из лучших практик.

В принципе, я надеялся, что кто-нибудь сможет поделиться своим опытом, какие предпочтения есть у других разработчиков и каков наилучший способ избежать каких-либо ошибок в будущем?

Переведено автоматически
Ответ 1

Разница между import module и from module import foo в основном субъективна. Выберите тот, который вам больше нравится, и будьте последовательны в его использовании. Вот несколько моментов, которые помогут вам определиться.

import module


  • Плюсы:

    • Меньше обслуживания ваших import инструкций. Не нужно добавлять никаких дополнительных импортов, чтобы начать использовать другой элемент из модуля


  • Минусы:

    • Ввод module.foo в вашем коде может быть утомительным и избыточным (скуку можно свести к минимуму, используя import module as mo then typing mo.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 ... когда я часто использую какой-либо объект / функцию в коде.

python