Python * импорт - PullRequest
       45

Python * импорт

12 голосов
/ 04 мая 2011

Мне обычно говорили, что следующее - плохая практика.

from module import *

Основная причина (или мне так сказали), что вы можете импортировать то, что вам не нужнои он может скрывать функцию или класс с таким же именем от другого модуля.

Однако, как насчет PyQt

from PyQt4.QtCore import *

Каждый пример, который я когда-либо видел, написан таким образом, главным образом потому, что всеэкспорт из Qt начинается с "Q", поэтому он не будет ничего скрывать.

Что такое консенсус?Неужели всегда плохо использовать * импорт?

РЕДАКТИРОВАТЬ:

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

По сути, я обнаружил, что кодирование в PEP8 улучшило мою читабельность кода, за исключением в отношении импорта PyQt4,и поэтому до сегодняшнего дня я не обращал внимания на недовольство пуристов.Но теперь моя группа разработчиков принимает решение об одном соглашении, и мне интересно, если это сценарий, «где практичность побеждает чистоту», или я должен просто смириться с этим и иметь дело с чудовищным импортом PyQt4

from PyQt4.QtGui import QComboBox, QLineEdit, QLayout, Q;lakdfaf.......

Ответы [ 8 ]

9 голосов
/ 04 мая 2011

Это может превратиться в религиозную войну. Это вопрос того, хотите ли вы быть явным или не хотите быть слишком многословным. В общем, следуя Zen of Python , лучше быть явным, но иногда людям просто не удобно перечислять каждый импорт из определенного модуля.

5 голосов
/ 04 мая 2011

Создание явного исключения для модулей, которые уже включают пространство имен в свое соглашение об именах (например, Q* из PyQT), вполне разумно. Тем не менее, я рекомендую четко указать, что по умолчанию все еще «не использовать его», и просто перечислить это исключение в ваших рекомендациях по кодированию.

import * также приемлемо, когда он используется как трюк манипулирования пространством имен в приложении (две знакомые мне формы - это дополнительные модули ускорения C, которые импортируются в конце чистой версии Python, и " "сплющивание" пространства имен пакета в __init__). Ключевым моментом является то, что импортирующий модуль и импортируемый модуль находятся под контролем одного и того же набора разработчиков, и, следовательно, предотвращение конфликтов пространства имен полностью находится под их контролем.

Последнее исключение сделано для удобства при интерактивной подсказке.

В других ситуациях лучше всего либо импортировать определенные имена, либо ссылаться на них косвенно через имя модуля (или, если есть некоторые обычно ссылочные элементы, сделать оба:

модуль импорта # Доступ к чему угодно из модуля import a, b, c # Но мы часто ссылаемся на них, поэтому извлекаем их напрямую

5 голосов
/ 04 мая 2011

Мое общее правило: если я не написал модуль, я не импортирую его все. Больше всего я боюсь писать локальные переменные, которые могли быть определены в импортированном модуле. Поэтому, чтобы избежать необходимости вводить длинные имена модулей, я использую импорт как функцию. Используя ваш модуль в качестве примера, я бы сделал следующее:

import PyQt4.QtCore as qt

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

Редактировать за комментарий
Когда я использую импорт *, мои модули поддержки не содержат классов или чего-либо, что может создать новый экземпляр. Они, как правило, представляют собой группы функций, которые модифицируют только существующие экземпляры. Чтобы уточнить мое мнение: если я являюсь владельцем исходного кода и буду основным сопровождающим, я буду использовать импорт *, иначе я бы использовал импорт как.

Другая причина, по которой я использую функцию импорта в качестве функции, - это возможность макетировать модули для целей отладки. В проекте, над которым я сейчас работаю, я использую pyVisa для общения с несколькими устройствами GPIB. Когда я не подключен к сети GPIB устройств, я могу использовать модуль dummy_visa для записи в стандартный вывод (чтобы убедиться, что я отправляю правильный формат) и вернуть случайное число (для проверки моего приложения). Смотри ниже

if visa_debug:
    import dummy_visa as visa
else:
    import visa
gpib = visa.Instrument("GPIB0::10")
gpib.write("MEAS:VOLT?")
3 голосов
/ 04 мая 2011

В общем, если вы собираетесь использовать from X import Y, неплохо бы четко указать, что вы импортируете. Это не только потому, что это безопаснее, но и потому, что это делает ваш код более читабельным (а обновления до сторонних модулей, которые вы используете, не будут иметь такого большого потенциала, чтобы случайно сломать ваш код).

В некоторых примерах кода, демонстрирующих большие пакеты, такие как Qt или matplotlib, в примерах будет использоваться from module import *, потому что они часто импортируются только из одного модуля, и это сохраняет типизацию и позволяет их примеру кода добраться до сути. Нет никакой причины, по которой вы не можете сделать это в своем коде, но, по крайней мере, используйте его в качестве модератора, особенно если он находится в больших исходных файлах, или другие люди будут смотреть на ваш код.

3 голосов
/ 04 мая 2011

Я считаю, что import * подвергается насилию и может стать головной болью при обслуживании, поэтому я избегаю этого по этой и другим причинам, о которых вы заявляете.Тем не менее, я чувствую, что это нормально для коротких интерактивных сессий, например, from pylab import *.

В рабочем коде, для пакетов типа PyQt4.QtCore, где вы планируете использовать много символов, я бы использовал один из следующихсинтаксисы, которые делают явным, из какого пространства имен взяты символы:

from PyQt4 import QtCore
# explicit where the symbol came from
QtCore.QTime()

import PyQt4.QtCore as QT
# less desirable since you need to look in the header to find out what QT is
# but I still prefer it to import *
QT.QTime()
3 голосов
/ 04 мая 2011

Tutorial, chapter 6 :

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

Учебник, глава 10 :

Обязательно используйте импортСтиль ОС вместо ОС импорта *.Это не даст os.open () скрывать встроенную функцию open (), которая работает по-разному.

Так что иногда это определенно плохая идея;не самая лучшая идея большую часть времени;и приемлемый ярлык в случаях, когда вы хотите печатать меньше, например, в интерактивных сеансах.

2 голосов
/ 04 мая 2011

Дизайн PyQt - это вода под мостом.Я не уверен, что это лучшее, но, вероятно, на это повлияло то, как был разработан Qt.AFAIK, Qt исторически не использовал пространства имен C ++ (я не уверен, использует ли он их сейчас), и поэтому должен был использовать префиксы.Но все эти дизайнерские решения, вероятно, произошли более 10 лет назад, и это не должно повлиять на ваши дизайнерские решения сейчас .

Я знаю, что если бы я проектировал библиотеку сейчас, я быопределенно решите использовать пространства имен пакетов (которые вы бы явно импортировали в Python) поверх префиксов.Допустим, мой префикс - Pfx - если пользователю библиотеки наплевать на PfxFunc() каждый раз, когда ему нужна функция, ему, безусловно, не понадобятся дополнительные символы в Pfx.Func(), особенно когда он может использовать импорт с определенным символом.имена, чтобы сократить это еще больше.

1 голос
/ 04 мая 2011

Рассмотрим этот случай

from foo import *
from bar import *

x=baz()

Теперь предположим, что foo имеет функцию с именем baz(), которую мы используем в нашем коде, и все работает нормально. Проходят месяцы или годы, автор bar добавляет функцию под названием baz(). Кто-то обновляет яйцо и бинго - в программе потенциально трудно обнаружить ошибку.

Не говоря уже о том, что, просто взглянув на эти три строки кода, я не могу сказать, откуда взялась baz, не взглянув на foo и bar

Единственный раз, когда я бы использовал import *, было бы в переводчике, чтобы сохранить набор текста

...