Почему «импорт *» плох? - PullRequest
127 голосов
/ 05 марта 2010

Рекомендуется не использовать import * в Python.

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

Ответы [ 12 ]

196 голосов
/ 05 марта 2010
  • Потому что он помещает много вещей в ваше пространство имен (может затенить какой-то другой объект из предыдущего импорта, и вы не будете знать об этом).

  • Поскольку вы не знаете точно, что импортируется, и не можете легко найти, из какого модуля была импортирована определенная вещь (удобочитаемость).

  • Поскольку вы не можете использовать классные инструменты, такие как pyflakes, для статического обнаружения ошибок в вашем коде.

42 голосов
/ 05 марта 2010

Согласно Zen of Python :

Явное лучше, чем неявное.

... не могу с этим поспорить, конечно?

37 голосов
/ 16 марта 2010

Вы не передаете **locals() функциям?

Поскольку в Python отсутствует оператор "include", и параметр self является явным, правила определения области действия и довольно просты, обычно очень легко указать пальцем на переменная и сообщает откуда этот объект - без чтения других модулей и без какой-либо IDE (которые в любом случае ограничены в способе самоанализа из-за того, что язык очень динамичен).

import * ломает все это.

Кроме того, он имеет конкретную возможность скрывать ошибки.

import os, sys, foo, sqlalchemy, mystuff
from bar import *

Теперь, если модуль bar имеет какой-либо из атрибутов "os", "mystuff" и т. Д., Они будут переопределять явно импортированные атрибуты и, возможно, будут указывать на совершенно разные вещи. Определение __all__ в строке часто целесообразно - здесь указывается, что будет импортироваться неявным образом, - но все же трудно отследить, откуда берутся объекты, не читая и не анализируя модуль бара и не следуя его импортам. Сеть import * - это первое, что я исправляю, когда вступаю во владение проектом.

Не поймите меня неправильно: если бы не было 1025, я бы заплакал, чтобы получить его. Но это должно быть использовано осторожно. Хорошим вариантом использования является предоставление интерфейса фасада поверх другого модуля. Аналогично, использование операторов условного импорта или импорта внутри пространств имен функций / классов требует некоторой дисциплины.

Я думаю, что в средних и больших проектах, или небольших, с несколькими участниками, требуется минимум гигиены с точки зрения статического анализа - запуск по крайней мере pyflakes или, что еще лучше, правильно настроенного pylint - чтобы поймать несколько видов ошибок, прежде чем они произойдут.

Конечно, поскольку это python - не стесняйтесь нарушать правила и исследовать - но опасайтесь проектов, которые могут вырасти в десять раз, если в исходном коде отсутствует дисциплина, это будет проблемой.

16 голосов
/ 05 марта 2010

Это потому, что вы загрязняете пространство имен.Вы импортируете все функции и классы в собственное пространство имен, которое может конфликтовать с функциями, которые вы определяете сами.

Кроме того, я думаю, что использование квалифицированного имени более понятно для задачи обслуживания;Вы видите в самой строке кода, откуда взялась функция, так что вы можете намного проще просматривать документы.

В модуле foo:

def myFunc():
    print 1

В вашем коде:

from foo import *

def doThis():
    myFunc() # Which myFunc is called?

def myFunc():
    print 2
15 голосов
/ 05 марта 2010

Можно сделать from ... import * в интерактивном сеансе.

10 голосов
/ 05 марта 2010

http://docs.python.org/tutorial/modules.html

Обратите внимание, что в целом практика импорта * из модуля или пакета не одобряется, так как это часто вызывает плохо читаемый код .

8 голосов
/ 05 марта 2010

Скажем, у вас есть следующий код в модуле с именем foo:

import ElementTree as etree

и затем в вашем собственном модуле у вас есть:

from lxml import etree
from foo import *

Теперь у вас есть трудный для отладки модуль, который выглядит как , в нем есть этри из lxml, но вместо него действительно ElementTree.

7 голосов
/ 27 декабря 2015

Это все хорошие ответы. Я хочу добавить, что при обучении новых людей программированию на 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., и тогда появится список автозаполнения. Atom.io screenshot

6 голосов
/ 26 декабря 2016

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

  • Когда я хочу структурировать свой код таким образом, чтобы все константы шли в модуль с именем const.py:
    • Если я сделаю import const, то для каждой константы я буду называть ее const.SOMETHING, что, вероятно, не самый удобный способ.
    • Если я сделаю from const import SOMETHING_A, SOMETHING_B ..., то, очевидно, это слишком многословно и побеждает цель структурирования.
    • Таким образом, я чувствую, что в этом случае выполнение from const import * может быть лучшим выбором.
3 голосов
/ 03 мая 2017

В качестве теста я создал модуль test.py с 2 функциями A и B, которые соответственно выдают «A 1» и «B 1». После импорта test.py с:

import test

. , , Я могу запустить две функции как test.A () и test.B (), и «test» отображается как module в пространстве имен, поэтому, если я отредактирую 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 *
...