В Python рекомендуется использовать import *
.
Может ли кто-нибудь объяснить причину этого, чтобы я мог избежать этого в следующий раз?
В Python рекомендуется использовать import *
.
Может ли кто-нибудь объяснить причину этого, чтобы я мог избежать этого в следующий раз?
Потому что он помещает много материала в ваше пространство имен (может тень другого объекта из предыдущего импорта, и вы не узнаете об этом).
Поскольку вы не знаете точно, что импортировано и не может легко найти, из какого модуля была импортирована определенная вещь (читаемость).
Поскольку вы не можете использовать классные инструменты, такие как pyflakes
, чтобы статически обнаруживать ошибки в вашем коде.
Согласно дзену питона:
Явное лучше, чем неявное.
... не могу с этим поспорить, конечно?
Вы не проходите **locals()
к функциям, не так ли?
Так как Python не имеет оператора include, а параметр self
является явным, а правила определения области действия довольно просты, обычно очень легко указать палец на переменную и указать, откуда этот объект - без чтения другие модули и без какой-либо IDE (которые в любом случае ограничены методом интроспекции, поскольку язык очень динамичен).
import *
ломает все это.
Кроме того, у него есть конкретная возможность скрывать ошибки.
import os, sys, foo, sqlalchemy, mystuff
from bar import *
Теперь, если в баровом модуле есть какие-либо атрибуты "os
", "mystuff
" и т.д., они переопределяют явно импортированные и, возможно, указывают на очень разные вещи. Определение __all__
в баре часто бывает мудрым - это указывает на то, что имплицитно будет импортировано, но все равно трудно отслеживать, откуда возникают объекты, без чтения и разбора модуля бара и после его импорта. Сеть import *
- это первое, что я исправляю, когда я беру на себя ответственность за проект.
Не поймите меня неправильно: если бы import *
отсутствовали, я бы заплакал, чтобы получить его. Но его нужно использовать осторожно. Хорошим вариантом является предоставление интерфейса фасада над другим модулем.
Аналогично, использование условных операторов импорта или импорт внутри пространств имен функций/классов требует некоторой дисциплины.
Я думаю, что в средних и крупных проектах или небольших с несколькими вкладчиками минимальная гигиена необходима с точки зрения статического анализа - при использовании, по крайней мере, пеплета или даже лучше правильно настроенной пилинга, - чтобы поймать несколько видов ошибок до того, как они произойдут.
Конечно, поскольку это python - не стесняйтесь нарушать правила и исследовать - но будьте осторожны с проектами, которые могут расти в десять раз, если исходный код отсутствует в дисциплине, это будет проблемой.
Это потому, что вы загрязняете пространство имен. Вы импортируете все функции и классы в свое собственное пространство имен, которое может столкнуться с функциями, которые вы сами определяете.
Кроме того, я думаю, что использование квалифицированного имени более понятно для задачи обслуживания; вы видите на самой кодовой строке, откуда приходит функция, поэтому вы можете легко проверить документы.
В модуле foo:
def myFunc():
print 1
В вашем коде:
from foo import *
def doThis():
myFunc() # Which myFunc is called?
def myFunc():
print 2
В интерактивном сеансе можно выполнить from ... import *
.
http://docs.python.org/tutorial/modules.html
Обратите внимание, что в целом практика импорта
*
из модуля или пакета неодобрилась, поскольку часто вызывает плохо читаемый код.
Скажем, у вас есть следующий код в модуле foo:
import ElementTree as etree
а затем в вашем собственном модуле вы:
from lxml import etree
from foo import *
Теперь у вас есть сложный для отладки модуль, который выглядит так, как будто в нем есть lxml etree, но на самом деле имеет ElementTree.
Все это хорошие ответы. Я собираюсь добавить, что при обучении новых людей программировать на Python, дело с import *
очень сложно. Даже если вы или они не записали код, это все еще камень преткновения.
Я преподаю детям (около 8 лет) программировать на Python, чтобы манипулировать Minecraft. Мне нравится предоставлять им полезную среду кодирования для работы с (Atom Editor) и преподавать REPL-ориентированную разработку (через bpython). В Atom я обнаружил, что подсказки/завершение работают так же эффективно, как и bpython. К счастью, в отличие от некоторых других инструментов статистического анализа Atom не обманывается import *
.
Однако, давайте возьмем этот пример... В этой обертке они from local_module import *
объединяют модули, включая этот список блоков. Пусть игнорируют риск конфликтов пространства имен. Делая from mcpi.block import *
, они делают весь этот список неясных типов блоков тем, что вам нужно посмотреть, чтобы узнать, что доступно. Если бы они использовали from mcpi import block
, то вы могли бы ввести walls = block.
, а затем появится список автозаполнения.
Понял действительные точки, которые люди здесь поставили. Тем не менее, у меня есть один аргумент, что иногда "звездный импорт" не всегда может быть плохой практикой:
const.py
: import const
, то для каждой константы я должен ссылаться на нее как const.SOMETHING
, что, вероятно, не самый удобный способ.from const import SOMETHING_A, SOMETHING_B...
, то, очевидно, это слишком многословно и побеждает цель структурирования.from const import *
может быть лучшим выбором.Практика очень низкая по двум причинам:
Для точки 1: Рассмотрим пример:
from module1 import *
from module2 import *
from module3 import *
a = b + c - d
Здесь, увидев код, никто не получит представление о том, из какого модуля b
, c
и d
действительно принадлежит.
С другой стороны, если вы это сделаете:
# v v will know that these are from module1
from module1 import b, c # way 1
import module2 # way 2
a = b + c - module2.d
# ^ will know it is from module2
Это намного более чистое для вас, а также новый человек, присоединившийся к вашей команде, будет иметь лучшую идею.
Для точки 2: пусть говорят, что как module1
, так и module2
имеют переменную как b
. Когда я это сделаю:
from module1 import *
from module2 import *
print b # will print the value from module2
Здесь значение из module1
теряется. Будет сложно отлаживать, почему код не работает, даже если b
объявлен в module1
, и я написал код, ожидающий, что мой код будет использовать module1.b
Если у вас одинаковые переменные в разных модулях, и вы не хотите импортировать весь модуль, вы можете даже сделать:
from module1 import b as mod1b
from module2 import b as mod2b
В качестве теста я создал модуль test.py с двумя функциями A и B, которые соответственно печатают "A 1" и "B 1". После импорта test.py с помощью:
import test
., Я могу запустить 2 функции, поскольку test.A() и test.B() и "test" отображаются в модуле в пространстве имен, поэтому, если я редактирую test.py, я могу перезагрузить его с:
import importlib
importlib.reload(test)
Но если я сделаю следующее:
from test import *
в пространстве имен нет ссылки на "тест", поэтому нет способа перезагрузить его после редактирования (насколько я могу судить), что является проблемой в интерактивном сеансе. Если одно из следующих значений:
import test
import test as tt
добавит "test" или "tt" (соответственно) в качестве имен модулей в пространстве имен, что позволит перезагрузить.
Если я это сделаю:
from test import *
имена "A" и "B" отображаются в пространстве имен как функции. Если я отредактирую test.py и повторю вышеприведенную команду, измененные версии функций не будут перезагружены.
И следующая команда вызывает сообщение об ошибке.
importlib.reload(test) # Error - name 'test' is not defined
Если кто-то знает, как перезагрузить модуль, загруженный с "из импорта модуля", отправьте сообщение. В противном случае это было бы еще одной причиной, чтобы избежать формы:
from module import *
Как предлагается в документации, вы никогда не должны использовать import *
в производственном коде.
В то время как импорт *
из модуля плох, импорт * из пакета еще хуже. По сути, from package import *
импортируется любое имя, определенное пакетом __init__.py
, но оно также включает любые подмодули пакета, которые были загружены предыдущими операторами import
.
Рассмотрим этот пример:
# anywhere in the code before import *
import sound.effects.echo
import sound.effects.surround
# in your module
from sound.effects import *
Последний оператор импортирует модули echo
и surround
в текущее пространство имен (возможно, переопределяя предыдущие определения), потому что они определены в пакете sound.effects
при выполнении оператора import
.