在函数内部导入Python模块和/或函数,在效率、速度和内存方面有哪些优点和缺点?
它是在每次函数运行时重新导入,还是在函数是否运行时只在开始时导入一次?
它在函数第一次执行时导入一次。
优点:
缺点:
它在第一次调用函数时导入一次。
如果我在导入的模块中有一个很少使用的函数,并且是唯一需要导入的函数,我可以想象这样做。看起来有点牵强附会……
在函数内部导入将有效地导入模块一次。函数第一次运行时。
无论您是在顶部导入它,还是在函数运行时导入它,它都应该导入得一样快。这通常不是一个在定义中导入的好理由。优点是什么?如果函数没有被调用,它将不会被导入。这实际上是一个合理的原因,如果你的模块只要求用户安装某个模块,如果他们使用你的特定功能…
如果这不是你做这件事的原因,那几乎可以肯定这是个恶心的主意。
它是否在每次函数运行时都重新导入?
没有;或者说,Python模块在每次导入时本质上都是缓存的,因此第二次(或第三次,或第四次……)导入实际上并不会迫使它们再次经历整个导入过程。1
无论函数是否运行,它是否在开始时导入一次?
不,它只在函数执行时被导入。2, 3.
至于好处,我想这要看情况。如果你可能只很少运行一个函数,并且不需要在其他任何地方导入该模块,则只在该函数中导入它是有益的。或者如果存在名称冲突或其他原因,您不希望模块或模块中的符号可用到处都是,您可能只想在特定函数中导入它。(当然,对于这些情况,总是有from my_module import my_function as f。)
from my_module import my_function as f
在一般的实践中,它可能没有那么有益。事实上,大多数Python风格指南鼓励程序员将所有导入都放在模块文件的开头。
当你第一次从任何地方(函数内部或外部)import goo时,goo.py(或其他可导入的形式)被加载,并且sys.modules['goo']被设置为这样构建的模块对象。任何将来在程序的相同运行中导入(同样,无论是在函数内部还是外部)只需查找sys.modules['goo']并将其绑定到适当范围内的假名goo。字典查找和名称绑定是非常快速的操作。
import goo
goo.py
sys.modules['goo']
goo
假设第一个import在程序的运行中完全平摊,将“适当的作用域”设置为模块级意味着每次使用goo.this、goo.that等都是两次字典查找——一次用于goo,一次用于属性名。如果它是“函数级”,每次运行函数都需要额外设置一个局部变量(甚至比字典查找部分还要快!),但每次goo.this(等)访问都可以节省一个字典查找(将其转换为局部变量查找,非常快),基本上可以将此类查找所需的时间减半。
import
goo.this
goo.that
我们讨论的是几纳秒,所以这几乎是一个值得优化的优化。在函数中使用import的一个潜在的重大优势是,在给定的程序运行中,该函数可能根本不需要,例如,该函数通常处理错误、异常和罕见情况;如果是这种情况,任何不需要该功能的运行甚至都不会执行导入(这节省了微秒,而不仅仅是纳秒),只有确实需要该功能的运行才会付出代价(适度但可衡量)。
这仍然是一种只有在非常极端的情况下才有价值的优化,在尝试以这种方式挤出微秒之前,我还会考虑许多其他优化。
我是否可以建议在一般情况下,而不是问,“X将提高我的性能?”你使用剖析来确定你的程序实际上花费它的时间,然后根据你将得到最大的好处应用优化?
然后,您可以使用分析来确保您的优化实际上也使您受益。