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

Tim*_*ton 142 python python-import

在速度和内存效率方面,在函数内导入Python模块和/或函数的优缺点是什么?

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

mip*_*adi 130

每次运行该功能时是否重新导入?

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

无论函数是否运行,它都会在开头导入一次吗?

不,只有在执行该功能时才导入它.

至于好处:这取决于我猜.如果您可能很少运行函数并且不需要在其他任何地方导入模块,那么仅在该函数中导入它可能是有益的.或者,如果存在名称冲突或其他原因,您不希望模块中的模块或符号随处可用,您可能只想在特定函数中导入它.(当然,from my_module import my_function as f这些情况总是如此.)

在一般实践中,它可能没那么有益.实际上,大多数Python样式指南都鼓励程序员将所有导入放在模块文件的开头.

  • 在同一思路中,如果将导入隐藏在辅助函数中,这可以使依赖项成为可选项. (13认同)
  • 当我为自己编写库模块时,我将它用于可选的依赖项.我使库模块中的每个函数都依赖于最小数量的导入. (5认同)
  • 谢谢!它通过将慢速模块 `importplotly` 放在调用它的函数中,节省了我的 web2py 应用程序大量的加载时间。 (3认同)
  • @PatrickT 如果您使用 IDE,他们往往会告诉您导入是否未访问。例如,在 VSCode 中,Pylance 会告诉我是否没有访问导入。 (3认同)
  • 我发现有时我需要 **package A** 来完成特定任务。后来我重写了代码并决定使用 **package B** 代替。那时,我可能不记得**包 A** 是否在我的项目中的其他地方使用过,并且可能在不再需要时不删除它,或者在仍然需要时删除它(如果我不会立即注意到这一点)这是代码中很少使用的部分)。我想知道当你不导入内部函数时,其他人是否会采取一些措施来避免此类问题? (2认同)

Ale*_*lli 39

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

假设第一个import越过程序的运行完全摊销反正,具有"合理范围"是模块级指的每次使用goo.this,goo.that等等,是二字典查找-一个用于goo和一个用于属性名称.让它成为"功能级别"每次运行函数都会支付一个额外的局部变量设置(甚至比字典查找部分更快!)但是为每个运行节省了一个dict查找(将其交换为局部变量查找,非常快)goo.this(等)访问,基本上减少了这种查找所花费的时间.

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

它仍然是一种在非常极端情况下值得的优化,并且在尝试以这种方式挤出微秒之前还有许多其他的考虑因素.

  • 首次导入模块非常昂贵.尝试运行一个空脚本与一个只包含`import string,itertools,fractions,heapq,re,array,bisect,collections,math,os`的脚本.第一个平均为180毫秒,第二个为230毫秒.所以对于初学者来说,这不是微秒.这是几十毫秒(可能是光盘访问?).这对于运行多次的小型脚本非常重要(例如,可能提供Web请求). (3认同)
  • @TobiasKienzler仍然适用于FaaS(功能即服务)环境和/或某些低性能(例如嵌入式)设备。该论点是等待时间的差异可能很大,并且不能简单地忽略它。 (2认同)

Sil*_*ost 10

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

优点:

  • 与他们使用的功能相关的导入
  • 易于移动包装周围的功能

缺点:

  • 看不出这个模块可能依赖的模块

  • 如果您执行`grep import / path / to / module`之类的操作,它将向您显示它导入的所有模块。 (2认同)

gom*_*mad 8

我是否可以总体上建议,而不是问“X 会提高我的表现吗?” 您使用分析来确定您的程序实际花费时间的位置,然后根据您将获得最大收益的位置应用优化?

然后您可以使用分析来确保您的优化实际上也使您受益。

  • 我同意这一点,这更像是一个好奇的问题。我想知道 Python 的 import 方法如何更详细地工作,而不是试图进行过早的性能增强。不过还是谢谢:) (4认同)
  • 啊。好了,希望这里的优秀回答满足了你的好奇心!Effbot 提供了一些可能对您有用的信息:http://effbot.org/zone/import-confusion.htm 向下滚动到“Python 如何导入模块?” (3认同)

roy*_*yal 5

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

无论是在顶部导入还是在运行函数时,它都应该以同样的速度导入.这通常不是导入def的好理由.优点?如果没有调用该函数,它将不会被导入..这实际上是一个合理的理由,如果你的模块只需要用户安装某个模块,如果他们使用你的特定功能...

如果他不是因为你这样做,那几乎可以肯定是一个令人讨厌的想法.