В Python, что происходит при импорте внутри функции?

Каковы преимущества и недостатки импорта модуля и/или функции Python внутри функции в отношении эффективности скорости и памяти?

Повторно ли он импортируется каждый раз при запуске функции или, возможно, только один раз в начале будет ли функция запущена?

Ответ 1

Повторно импортирует ли он каждый раз при запуске функции?

Нет; или, скорее, модули Python по сути кэшируются при каждом импорте, поэтому импорт второго (или третьего, или четвертого...) времени фактически не заставляет их снова проходить весь процесс импорта. 1

Импортирует ли он один раз в начале, запущена ли функция?

Нет, он импортируется только тогда и когда функция выполняется. 2, 3

Что касается преимуществ: это зависит, я думаю. Если вы можете запускать функцию очень редко и не нуждаетесь в импорте модуля куда-либо еще, может быть полезно импортировать его только в эту функцию. Или, если есть конфликт имен или другая причина, по которой вы не хотите, чтобы модуль или символы из модуля были доступны везде, вы можете импортировать его только в определенной функции. (Конечно, всегда есть from my_module import my_function as f для этих случаев.)

В общем, это, вероятно, не так выгодно. Фактически, большинство руководств по стилю Python побуждают программистов помещать все импортированные файлы в начало файла модуля.

Ответ 2

В первый раз, когда вы import goo из любого места (внутри или снаружи функции), goo.py (или другая импортируемая форма) загружается, а sys.modules['goo'] устанавливается на объект модуля, построенный таким образом. Любой будущий импорт в рамках одного и того же запуска программы (опять же, внутри или вне функции) просто ищет sys.modules['goo'] и привязывает его к barename goo в соответствующей области. Поиск по имени и привязке имени - очень быстрые операции.

Предполагая, что самый первый import полностью амортизируется по программному запуску, наличие "соответствующей области видимости" на уровне модуля означает, что каждое использование goo.this, goo.that и т.д. - это два поиска по типу - один для goo и один для имени атрибута. Если он будет "функциональным уровнем", он платит один дополнительный параметр локальной переменной за запуск функции (даже быстрее, чем часть поиска в словаре!), Но сохраняет один поиск в dict (обменивая его на поиск по локальной переменной, невероятно быстро) для каждого goo.this (и т.д.), в основном, в два раза меньше времени, необходимого для поиска.

Мы говорим о нескольких наносекундах так или иначе, так что это вряд ли стоит оптимизировать. Одним из потенциально существенных преимуществ использования import внутри функции является то, что эта функция может вообще не понадобиться в данном запуске программы, например, эта функция имеет дело с ошибками, аномалиями и в редких ситуациях в целом; если в этом случае любой прогон, который не нуждается в функциональности, даже не будет выполнять импорт (и что сохранение микросекунд, а не только наносекунд), работает только те, которые действительно нуждаются в функциональности, будут платить (скромную, но измеримую) цену.

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

Ответ 3

Он импортирует один раз, когда функция выполняется в первый раз.

Плюсы:

  • импорт, связанный с функцией, которую они используют в
  • легко перемещать функции вокруг пакета

Минусы:

  • не мог видеть, какие модули этот модуль может зависеть от

Ответ 4

Импорт внутри функции будет эффективно импортировать модуль один раз.. при первом запуске функции.

Он должен импортироваться так же быстро, как вы импортируете его вверху или когда функция запускается. Это не является хорошей причиной для импорта в def. Плюсы? Он не будет импортирован, если функция не будет вызвана. Это действительно разумная причина, если ваш модуль требует, чтобы у пользователя был установлен определенный модуль, если они используют определенные ваши функции...

Если это не причина, по которой вы это делаете, это почти наверняка идея.

Ответ 5

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

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

Ответ 6

Он импортирует один раз, когда функция вызывается в первый раз.

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