在Python中,在函数内部导入时会发生什么?

在Python中,在函数内部导入时会发生什么?,python,python-import,Python,Python Import,就速度和内存效率而言,在函数内部导入Python模块和/或函数的利弊是什么 它是否在每次运行函数时重新导入,或者无论函数是否运行,在开始时只导入一次?它在函数第一次执行时导入一次 优点: 与所使用的函数相关的导入 易于在软件包中移动功能 缺点: 无法查看此模块可能依赖的模块 第一次调用函数时,它会导入一次 我可以想象这样做,如果我在一个导入的模块中有一个函数,它使用非常少,并且是唯一一个需要导入的模块。看起来有些牵强,不过…在函数内部导入将有效地导入模块一次。。第一次运行该函数时 无论是在

就速度和内存效率而言,在函数内部导入Python模块和/或函数的利弊是什么


它是否在每次运行函数时重新导入,或者无论函数是否运行,在开始时只导入一次?

它在函数第一次执行时导入一次

优点:

  • 与所使用的函数相关的导入
  • 易于在软件包中移动功能
缺点:

  • 无法查看此模块可能依赖的模块

第一次调用函数时,它会导入一次


我可以想象这样做,如果我在一个导入的模块中有一个函数,它使用非常少,并且是唯一一个需要导入的模块。看起来有些牵强,不过…

在函数内部导入将有效地导入模块一次。。第一次运行该函数时

无论是在顶部导入,还是在函数运行时,它都应该以同样快的速度导入。这通常不是在def中导入的好理由。赞成的意见?如果未调用该函数,则不会导入该函数。。这实际上是一个合理的理由,如果你的模块只要求用户安装某个模块,如果他们使用你的特定功能

如果这不是你这么做的原因,那几乎肯定是个恶心的主意

它是否在每次运行函数时重新导入

没有;或者更确切地说,Python模块在每次导入时都会被缓存,因此第二次(或第三次,或第四次…)导入实际上不会迫使它们再次完成整个导入过程

无论函数是否运行,它是否在开始时导入一次

否,仅当函数执行时才导入

至于好处:我想这要视情况而定。如果您可能很少运行某个函数,并且不需要在其他任何地方导入该模块,那么只在该函数中导入该模块可能是有益的。或者,如果由于名称冲突或其他原因,您不希望模块或模块中的符号在任何地方都可用,您可能只希望在特定函数中导入它。(当然,对于这些情况,总是有
从my_模块导入my_函数作为f


在一般实践中,这可能没有那么大的好处。事实上,大多数Python风格的指南都鼓励程序员将所有导入放在模块文件的开头。

第一次从任何地方(函数内部或外部)导入goo时,
goo.py
(或其他可导入的形式)被加载,并且
sys.modules['goo']
被设置为这样构建的模块对象。在程序的同一次运行中(同样,无论是在函数内部还是外部)的任何未来导入只需查找
sys.modules['goo']
,并将其绑定到相应范围内的barename
goo
。dict查找和名称绑定是非常快速的操作

假设第一次导入在程序的运行过程中被完全摊销,那么模块级的“适当范围”意味着每次使用,
goo。这是两个dict查找,一个用于
goo
,另一个用于属性名。将其设置为“函数级别”会在每次函数运行时额外支付一个局部变量设置(甚至比字典查找部分更快!),但每次
goo都会节省一个dict查找(将其替换为局部变量查找,速度非常快)。这样的访问
(etc)基本上将此类查找所需的时间减半

我们讨论的是几纳秒,所以这几乎不值得优化。在函数中具有
导入
的一个潜在实质性优势是,在给定的程序运行中可能根本不需要该函数,例如,该函数通常处理错误、异常和罕见情况;如果是这种情况,任何不需要该功能的运行都不会执行导入(这节省了微秒,而不仅仅是纳秒),只有需要该功能的运行才会付出(适度但可测量的)代价


这仍然是一个优化,在非常极端的情况下才是值得的,在尝试用这种方式挤出微秒之前,我会考虑很多其他问题。

< P>我可以一般地建议,而不是问,“X会提高我的性能吗?”您可以使用评测来确定您的程序在哪里实际花费时间,然后根据您从哪里获得最大好处来应用优化


然后,您可以使用评测来确保您的优化实际上也让您受益。

这种优化实际上是不值得的-即使模块已经加载,再多的快速局部变量访问也无法弥补调用
import
的难以置信的费用。检查模块是否已加载是一项非常昂贵的操作(相对于一些全局字典查找)。首次导入模块的成本很高。尝试运行一个空脚本,而不是只包含
导入字符串、itertools、分数、heapq、re、数组、对分、集合、数学、操作系统的脚本。第一个平均需要180毫秒,第二个平均需要230毫秒。所以对于初学者来说,这不是微秒。这是几十毫秒(可能会发生光盘访问?)。这对于多次运行的小型脚本(比如服务web请求)来说意义重大。@EvgeniSergeev在这种情况下,您通常有一台服务器一直在运行,因此它不会一次又一次地重新导入again@TobiasKienzler它仍然适用于FaaS(功能即服务)环境和/或某些低性能(例如嵌入式)器具。其理由是延迟的差异可能很大,不能简单地忽略。没有速度优势(调用
import