2012-01-27 4 views
6

В случае сомнений я обычно размещаю свои операторы импорта в верхней части модуля. Часто это сокращает повторение, что приятно. Однако есть ли недостаток производительности в случае, когда требуется только одна функция (или класс) для импорта?Python Импорт на уровне функции VS. Уровень модуля

выполняет следующие импорт только при вызове функции?

 def func(): 
     from task import test 

Если это так, я полагаю, что это может быть небольшой эффект. Я также предполагаю, что вы могли бы получить некоторые добавленные точки для более быстрой сборки мусора и изменения переменных, поскольку импортированные объекты не будут добавлены в глобальный словарь. В качестве другого плаката хорошо сказано:

Это главным образом связано с переменным взглядом. Для поиска переменной в глобальной области требуется поиск в словаре. Напротив, компилятор ставит статические локальные имена и ссылается на них по индексу, поэтому поиск словаря не требуется.

Являются ли эти справедливые предположения я полностью вне базы?

Благодаря

+2

Что касается производительности поиска имен: ** Это не имеет значения. ** В этом редком случае вы узнаете, когда вы закончили код, выяснили, что он слишком медленный и профилированный. – delnan

ответ

4

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

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

Я только импортирую модули в область действия по двум причинам: 1) устранить проблемы с циклическим импортом, которые, вероятно, могут быть решены другими способами путем рефакторинга или 2) если модуль является необязательным, а функция не является используемый многими из моих пользователей. В случае 2) модуль может быть полностью пропущен, и не будет проблем, если кто-то не вызовет эту функцию.

+0

Это был скорее теоретический вопрос. Кажется, есть разница, даже если она пренебрежимо мала. Спасибо Ned – Ben

+0

Это самый пифонический путь? Я вижу, что некоторые люди делают импорт на __init__.py в корне своего модуля и импортируют все оттуда. Может ли это быть использовано для решения определенных циклических импортных операций? – radtek

3

Давайте посмотрим на то, что байткод будет выглядеть для следующих двух функций:

def func1(): 
    """ test imported each time function is run """ 
    from task import test 
    test() 

def func2(): 
    """ test was imported at top of module """ 
    test() 

Как вы можете видеть ниже, func2() экономит много шагов, используя глобально импортируемого test функцию ,

>>> dis.dis(func1) 
    3   0 LOAD_CONST    1 (-1) 
       3 LOAD_CONST    2 (('test',)) 
       6 IMPORT_NAME    0 (task) 
       9 IMPORT_FROM    1 (test) 
      12 STORE_FAST    0 (test) 
      15 POP_TOP 

    4   16 LOAD_FAST    0 (test) 
      19 CALL_FUNCTION   0 
      22 POP_TOP 
      23 LOAD_CONST    3 (None) 
      26 RETURN_VALUE 
>>> dis.dis(func2) 
    3   0 LOAD_GLOBAL    0 (test) 
       3 CALL_FUNCTION   0 
       6 POP_TOP 
       7 LOAD_CONST    1 (None) 
      10 RETURN_VALUE 

Принимая это во внимание, возможно, преждевременная оптимизация, как указано в комментарии дельнана.

Что касается test, находящегося в глобальном пространстве имен, это вряд ли вызовет проблемы с производительностью поиска. Самый известный способ, я думаю, вы могли бы увидеть это, если бы было столкновение с хешем для test и другое имя, которое вы используете очень часто, что вызвало поиск второго имени, которое занимает больше времени. Опять же, преждевременная оптимизация, чтобы рассмотреть этот редкий случай впереди.

+1

Но обратите внимание, что он не будет импортировать модуль более одного раза - он просто проверяет, имеет ли он каждый раз, когда он вызывается. – delnan

+0

Спасибо, что выложите это; это полезно. Не был знаком с библиотекой. – Ben

0

Я думаю, что имеет смысл поставить импорт в определение, если его не вызывают очень часто.

Смежные вопросы