Импорт всегда помещается в начало файла, сразу после любых комментариев модуля и строк документации, а также перед глобальными значениями модуля и константами.
Однако, если класс / метод / функция, которые я импортирую, используются только в редких случаях, наверняка эффективнее выполнять импорт, когда это необходимо?
Не так ли:
classSomeClass(object):
defnot_often_called(self) from datetime import datetime self.datetime = datetime.now()
Импорт модуля происходит довольно быстро, но не мгновенно. Это означает, что:
Размещение импорта в верхней части модуля - это нормально, потому что это тривиальная стоимость, которая оплачивается только один раз.
Размещение импорта внутри функции приведет к тому, что вызовы этой функции будут занимать больше времени.
Итак, если вы заботитесь об эффективности, разместите импорт вверху. Перемещайте их в функцию только в том случае, если ваше профилирование показывает, что это поможет (вы сделали profile, чтобы увидеть, где лучше всего повысить производительность, верно ??)
Лучшие причины, которые я видел для выполнения отложенного импорта, следующие:
Поддержка дополнительных библиотек. Если в вашем коде есть несколько путей, использующих разные библиотеки, не прерывайте работу, если дополнительная библиотека не установлена.
В __init__.py плагине, который может быть импортирован, но фактически не используется. Примерами являются плагины Bazaar, которые используют bzrlib фреймворк с отложенной загрузкой.
Ответ 2
Помещение оператора импорта внутрь функции может предотвратить циклические зависимости. Например, если у вас есть 2 модуля, X.py и Y.py, и им обоим необходимо импортировать друг друга, это вызовет циклическую зависимость при импорте одного из модулей, вызывающую бесконечный цикл. Если вы переместите оператор импорта в один из модулей, то он не будет пытаться импортировать другой модуль, пока не будет вызвана функция, и этот модуль уже будет импортирован, поэтому бесконечного цикла не будет. Подробнее читайте здесь - effbot.org/zone/import-confusion.htm
Ответ 3
Я перенял практику размещения всего импорта в функциях, которые их используют, а не в верхней части модуля.
Преимущество, которое я получаю, - это возможность более надежного рефакторинга. Когда я перемещаю функцию из одного модуля в другой, я знаю, что функция продолжит работать со всем своим наследием тестирования без изменений. Если у меня есть мой импорт в верхней части модуля, то при перемещении функции я обнаруживаю, что в конечном итоге трачу много времени на то, чтобы импорт нового модуля был полным и минимальным. IDE для рефакторинга может сделать это неактуальным.
Существует ограничение скорости, как упоминалось в другом месте. Я измерил это в своем приложении и обнаружил, что оно незначительно для моих целей.
Также приятно иметь возможность видеть все зависимости модуля заранее, не прибегая к поиску (например, grep). Однако причина, по которой меня волнуют зависимости модулей, обычно заключается в том, что я устанавливаю, рефакторингую или перемещаю всю систему, состоящую из нескольких файлов, а не только один модуль. В таком случае я все равно собираюсь выполнить глобальный поиск, чтобы убедиться, что у меня есть зависимости системного уровня. Итак, я не нашел глобального импорта, который помог бы мне понять систему на практике.
Обычно я помещаю импорт sys внутри if __name__=='__main__' проверки, а затем передаю аргументы (например, sys.argv[1:]) в main() функцию. Это позволяет мне использовать main в контексте, где sys не был импортирован.
Ответ 4
В большинстве случаев это было бы полезно для наглядности и разумности выполнения, но это не всегда так. Ниже приведена пара примеров обстоятельств, при которых импорт модуля может выполняться в другом месте.
Во-первых, у вас мог бы быть модуль с модульным тестированием вида:
if __name__ == '__main__': import foo aa = foo.xyz() # initiate something for the test
Во-вторых, у вас может возникнуть требование условно импортировать какой-то другой модуль во время выполнения.
if [condition]: import foo as plugin_api else: import bar as plugin_api xx = plugin_api.Plugin() [...]
Вероятно, существуют другие ситуации, когда вы могли бы размещать импорт в других частях кода.