Python (и Django) лучшие практики импорта - PullRequest
21 голосов
/ 10 ноября 2009

Из различных способов импорта кода, есть ли способы, которые предпочтительнее использовать, по сравнению с другими? Эта ссылка http://effbot.org/zone/import-confusion.htm вкратце утверждает, что

from foo.bar import MyClass

не является предпочтительным способом импорта MyClass при нормальных обстоятельствах или если вы не знаете, что делаете. (Скорее, лучший способ хотел бы:

import foo.bar as foobaralias

и затем в коде для доступа к MyClass используйте

foobaralias.MyClass

)

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

Однако эта статья, на которую я ссылался, действительно старая.

Я также слышал, что лучше, по крайней мере в контексте проектов Django, вместо этого импортировать только те классы, которые вы хотите использовать, а не весь модуль. Было сказано, что эта форма помогает избежать ошибок кругового импорта или, по крайней мере, делает систему импорта django менее хрупкой. Было отмечено, что собственный код Django, похоже, предпочитает «из x import y», а не «import x».

Если в проекте, над которым я работаю, не используются какие-либо специальные функции __init__.py ... (все наши __init__.py файлы пусты), какой метод импорта следует выбрать и почему?

Ответы [ 3 ]

13 голосов
/ 10 ноября 2009

Первое и основное правило импорта: никогда не используйте from foo import *.

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

В большинстве случаев нет большой разницы между import foo и from foo import MyClass. Я предпочитаю второе, потому что здесь меньше набирается текста, но есть несколько причин, по которым я мог бы использовать первое:

  • Модуль и класс / значение имеют разные имена. Читателям может быть трудно вспомнить, откуда происходит конкретный импорт, когда имя импортированного значения не связано с модулем.

    • Хорошо: import myapp.utils as utils; utils.frobnicate()
    • Хорошо: import myapp.utils as U; U.frobnicate()
    • Плохо: from myapp.utils import frobnicate
  • Вы импортируете много значений из одного модуля. Сохрани свои пальцы и глаза читателя.

    • Плохо: from myapp.utils import frobnicate, foo, bar, baz, MyClass, SomeOtherClass, # yada yada
5 голосов
/ 10 ноября 2009

Для меня это зависит от ситуации. Если это метод / класс с уникальным именем (то есть, не process() или что-то в этом роде), и вы собираетесь использовать его лот , сохраните набор и просто наберите from foo import MyClass.

Если вы импортируете несколько вещей из одного модуля, вероятно, лучше просто импортировать модуль и выполнить module.bar, module.foo, module.baz и т. Д., Чтобы сохранить пространство имен в чистоте.

Вы также сказали

Было сказано, что эта форма помогает избежать ошибок кругового импорта или, по крайней мере, делает систему импорта django менее хрупкой. Было отмечено, что собственный код Django, похоже, предпочитает "from x import y", а не "import x".

Я не понимаю, как так или иначе можно было бы предотвратить круговой импорт. Причина в том, что даже когда вы делаете from x import y, ВСЕ из x импортируется. Только y заносится в текущее пространство имен, но обрабатывается весь модуль x. Попробуйте этот пример:

В test.py введите следующее:

def a():
    print "a"

print "hi"

def b():
    print "b"

print "bye"

Затем в runme.py введите:

from test import b

b()

Тогда просто сделай python runme.py

Вы увидите следующий вывод:

hi
bye
b

Итак, все в test.py было запущено, даже если вы только импортировали b

2 голосов
/ 10 ноября 2009

Преимущество последнего состоит в том, что происхождение MyClass является более явным. Первый помещает MyClass в текущее пространство имен, поэтому код может использовать MyClass без квалификации. Так что для кого-то менее очевидно, кто читает код, в котором определен MyClass.

...