Используйте "импорт модуля" или "из импорта модуля"?
Я попытался найти полное руководство о том, лучше ли использовать import module
или from module import
? Я просто начал с Python и я пытаюсь начать с лучших практик в виду.
в принципе, я надеялся, что если кто-то может поделиться своим опытом, какие предпочтения есть у других разработчиков и каков лучший способ избежать любого gotchas вниз по дороге?
13 ответов:
разницу между
import module
иfrom module import foo
в основном субъективные. Выберите тот, который вам больше всего нравится, и будьте последовательны в его использовании. Вот некоторые моменты, которые помогут вам решить.
import module
- плюсы:
- меньше обслуживания вашего
import
заявления. Не нужно добавлять никаких дополнительных импорта, чтобы начать использовать другой элемент из модуль- плюсы:
- введя
module.foo
в вашем коде может быть утомительным и избыточным (скука может быть сведена к минимуму с помощьюimport module as mo
введяmo.foo
)
from module import foo
- плюсы:
- меньше ввода для использования
foo
- больше контроля над тем, какие элементы модуля могут быть доступ
- плюсы:
- использовать новый элемент из модуля вы должны обновить свой
import
сообщении- вы теряете контекст о
foo
. Например, менее понятно, чтоceil()
не по сравнению сmath.ceil()
любой метод приемлем, но не использовать
from module import *
.для любого разумного большого набора кода, если вы
import *
вы вероятно, будет цементировать его в модуль, не может быть удален. Это связано с тем, что трудно определить, какие элементы, используемые в коде, поступают из "модуля", что позволяет легко добраться до точки, где вы думаете, что не используетеimport
больше, но это очень трудно быть уверенным.
здесь есть еще одна деталь, не упомянутая, связанная с записью в модуль. Конечно, это может быть не очень распространено, но мне это нужно время от времени.
из-за того, как ссылки и привязка имен работают в Python, если вы хотите обновить какой-либо символ в модуле, скажем foo.бар, снаружи этого модуля, и есть другой код импорта "см." это изменение, вы должны импортировать foo определенным образом. Например:
модуль foo:
bar = "apples"
модуль а:
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"
однако, если вы импортируете имена символов вместо имен модулей, это не будет работать.
например, если я делаю это в модуле:
from foo import bar bar = "oranges"
никакой код за пределами a не будет видеть бар как "апельсины", потому что моя настройка бара просто повлияла на имя" бар "внутри модуля a, он не" достиг "объекта модуля foo и не обновил его"бар".
оба способа поддерживаются по одной причине: бывают случаи, когда один из них более подходит, чем другой.
import module
: приятно, когда вы используете много битов из модуля. недостатком является то, что вам нужно будет квалифицировать каждую ссылку с именем модуля.
from module import ...
: приятно, что импортированные элементы можно использовать непосредственно без префикса имени модуля. Недостатком является то, что вы должны перечислить каждую вещь, которую вы используете, и что это не ясно в коде, где что-то пришло оттуда.что использовать зависит от того, что делает код понятным и читаемым, и имеет более чем мало общего с личными предпочтениями. Я наклоняюсь к
import module
Как правило, потому что в коде очень ясно, откуда появился объект или функция. Я используюfrom module import ...
когда я использую какой-то объект/функцию a много в коде.
хотя многие люди уже объяснили про
import
vsimport from
, я хочу попытаться объяснить немного больше о том, что происходит под капотом, и где все места, которые он меняет.
import foo
:импорт
foo
, и создается ссылка на этот модуль в текущем пространстве имен. Затем вам нужно определить завершенный путь модуля для доступа к определенному атрибуту или методу изнутри модуля.например.
foo.bar
но неbar
from foo import bar
:импорт
foo
, и создает ссылки на всех участников (bar
). Не устанавливает переменнуюfoo
.например.
bar
а неbaz
илиfoo.baz
from foo import *
:импорт
foo
, и создает ссылки на все общедоступные объекты, определенные этим модулем в текущем пространстве имен (все перечисленное в__all__
если__all__
существует, иначе все, что не запускается с_
). Не устанавливает переменнуюfoo
.например.
bar
иbaz
а не_qux
илиfoo._qux
.
теперь посмотрим, когда мы это сделаем
import X.Y
:>>> import sys >>> import os.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'>
Регистрация
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
из пространства имен locals() вы не сможете получить доступ кos
а такжеos.path
даже если они существуют в sys.модули:>>> 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' >>>
вы можете получить доступ, используя имя
path
а неos.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' >>>
Я лично всегда использую
from package.subpackage.subsubpackage import module
а затем получить доступ ко всему, как
module.function module.modulevar
etc. Причина в том, что в то же время у вас есть короткий вызов, и вы четко определяете пространство имен модуля каждой подпрограммы, что очень полезно, если вам нужно искать использование данного модуля в вашем источнике.
Излишне говорить, что не используйте импорт *, потому что он загрязняет ваше пространство имен и не говорит вам, откуда берется данная функция (из какого модуля)
конечно, вы можете столкнуться с проблемами, если у вас есть одно и то же имя модуля для двух разных модулей в двух разных пакетах, например
from package1.subpackage import module from package2.subpackage import module
в этом случае, конечно, вы столкнетесь с проблемами, но тогда есть сильный намек на то, что ваш макет пакета ошибочен, и вам нужно его переосмыслить.
import module
лучше всего, когда вы будете использовать много функций из модуля.
from module import function
лучше всего, когда вы хотите избежать загрязнения глобального пространства имен всеми функциями и типами из модуля, когда вам нужно только
function
.
вот еще одно отличие не упоминается. Это скопировано дословно из http://docs.python.org/2/tutorial/modules.html
обратите внимание, что при использовании
from package import item
элемент может быть либо подмодулем (или подпакетом) пакета, либо каким-либо другим именем, определенным в пакете, например функцией, классом или переменной. Оператор import сначала проверяет, определен ли элемент в пакете; если нет, он предполагает, что это модуль и пытается загрузить его. Если это не удается найти его, возникает исключение ImportError.
наоборот, при использовании синтаксиса типа
import item.subitem.subsubitem
каждый элемент, кроме последнего, должен быть пакетом; последний элемент может быть модулем или пакетом, но не может быть классом, функцией или переменной, определенной в предыдущем элементе.
я только что обнаружил еще одно тонкое различие между этими двумя методами.
если модуль
foo
использует следующий импорт:from itertools import count
модуль
bar
может по ошибке использоватьcount
как будто это было определено вfoo
, неitertools
:import foo foo.count()
если
foo
применение:import itertools
ошибка все еще возможна, но с меньшей вероятностью будет сделана.
bar
нужно:import foo foo.itertools.count()
это вызвало некоторые проблемы для меня. У меня был модуль, который по ошибке импортировал исключение из модуля, который не определял его, только импортировал его из другого модуля (используя
from module import SomeException
). Когда импорт больше не был нужен и удален, оскорбительный модуль был сломан.
добавить к тому, что люди говорят о
from x import *
: кроме того, что делает его более трудным, чтобы сказать, откуда пришли имена, это отбрасывает кодовые шашки, такие как Pylint. Они будут сообщать эти имена как неопределенные переменные.
import package import module
С
import
, токен должен быть модулем (файл, содержащий команды Python) или пакетом (папка вsys.path
, содержащий файл__init__.py
.)когда есть подпакеты:
import package1.package2.package import package1.package2.module
требования к папке (пакету) или файлу (модулю) одинаковы, но папка или файл должны быть внутри
package2
, который должен быть внутриpackage1
, а какpackage1
иpackage2
должен содержать__init__.py
файлы. https://docs.python.org/2/tutorial/modules.htmlС
from
стиль импорт:from package1.package2 import package from package1.package2 import module
пакет или модуль входит в пространство имен файла, содержащего
import
заявлениеmodule
(илиpackage
) вместоpackage1.package2.module
. Вы всегда можете привязать к более удобному имени:a = big_package_name.subpackage.even_longer_subpackage_name.function
только
from
стиль импорта позволяет вам назвать определенную функцию или переменную:from package3.module import some_function
разрешено, но
import package3.module.some_function
не допускается.
мой собственный ответ на это зависит в основном от первого, сколько различных модулей я буду использовать. Если я буду использовать только один или два, я буду часто использовать
from
...import
так как это делает для меньшего количества нажатий клавиш в остальной части файла, но если я собираюсь использовать много различных модулей, я предпочитаю простоimport
потому что это значит, что каждая ссылка на модуль самодокументируемыми. Я могу видеть, откуда каждый символ приходит без необходимости охотиться вокруг.обычно я предпочитаю стиль самостоятельного документирования простого импорта и только меняю его на from.. импорт, когда количество раз, когда я должен ввести имя модуля, растет выше 10 до 20, даже если импортируется только один модуль.
так как я тоже новичок, я буду пытаться объяснить это в простой форме: В Python, у нас есть три типа
import
инструкции:1. Общий импорт:
import math
этот тип импорта является моим личным фаворитом, единственным недостатком этого метода импорта является то, что если вам нужно использовать функцию любого модуля, вы должны использовать следующий синтаксис:
math.sqrt(4)
конечно, это увеличивает ввода но как Новичок, это поможет вам отслеживать модуль и функцию, связанную с ним, (хороший текстовый редактор значительно сократит усилие ввода и рекомендуется).
усилие ввода может быть дополнительно уменьшено с помощью этого оператора импорта:
import math as m
теперь, вместо того, чтобы использовать
math.sqrt()
можно использоватьm.sqrt()
.2. Функция импорт:
from math import sqrt
этот тип импорта лучше всего подходит, если ваш код должен получить доступ только к одной или нескольким функциям из модуля, но для использования любого нового элемента из модуля вам нужно обновить оператор импорта.
3. Универсальный импорт:
from math import
хотя это значительно снижает усилие ввода, но не рекомендуется, потому что он будет заполнять ваш код различными функциями из модуля и их имя может конфликтовать с именем определяемых пользователем функций. пример:
если у вас есть функция с вашим собственным именем sqrt и вы импортируете математику, ваша функция безопасна: есть ваш sqrt и есть математика.функция sqrt. Если вы делаете из math import *, однако, у вас есть проблема: а именно, две разные функции с одинаковым именем. Источник:Codecademy
импорт модуля-вам не нужно дополнительных усилий, чтобы получить еще одну вещь из модуля. Он имеет такие недостатки, как избыточный ввод
импорт модуля из-Меньше ввода и больше контроля над тем, какие элементы модуля могут быть accessed.To используйте новый элемент из модуля, который необходимо обновить оператор импорта.