Python - 导入函数和本地声明它之间的性能差异?

时间:2018-02-01 05:52:29

标签: python performance runtime

导入函数与在Python中的当前文件中声明函数之间的性能是否存在显着差异?

我有一个小功能(单行),我经常在我的程序中的几个 .py 文件中使用。我想改为定义一次,以便我对它做出的改变反映在任何地方。但是,我不确定将它用作导入函数是否会在调用它时增加额外的开销......

2 个答案:

答案 0 :(得分:0)

Hi Jet Blue,以便更好地理解python wiki PerformanceTips

  

import语句几乎可以在任何地方执行。将它们置于函数内以限制其可见性和/或缩短初始启动时间通常很有用。虽然Python的解释器经过优化,不能多次导入同一个模块,但在某些情况下,重复执行import语句会严重影响性能。

     

考虑以下两段代码(最初来自Greg McFarlane,我相信 - 我发现它在comp.lang.python python-list@python.org帖子中未归属,后来在另一个来源中归于他):

def doit1():
    import string ###### import statement inside function
    string.lower('Python')

for num in range(100000):
    doit1()
  

或:

import string ###### import statement outside function
def doit2():
    string.lower('Python')

for num in range(100000):
    doit2()
  

doit2的运行速度比doit1快得多,即使在doit2中对字符串模块的引用是全局的。这是一个使用Python 2.3运行的Python解释器会话和新的timeit模块,它显示第二个模块比第一个模块快多少:

def doit1():
    import string
    string.lower('Python')

import string
def doit2():
    string.lower('Python')

import timeit
t = timeit.Timer(setup='from __main__ import doit1', stmt='doit1()')
t.timeit()
11.479144930839539
t = timeit.Timer(setup='from __main__ import doit2', stmt='doit2()')
t.timeit()
4.6661689281463623
  

在Python 2.0中引入了字符串方法。这些提供了一个完全避免导入并且运行速度更快的版本:

def doit3():
    'Python'.lower()

for num in range(100000):
    doit3()
  

以下是来自时间的证明:

def doit3():     “Python'.lower()

t = timeit.Timer(setup ='from main import doit3',stmt ='doit3()') t.timeit() 2.5606080293655396

  

上面的例子显然有点人为,但一般原则仍然存在。

     

请注意,在函数中放入导入可以加快模块的初始加载速度,尤其是在可能不需要导入的模块的情况下。这通常是“懒惰”优化的情况 - 避免工作(导入模块,这可能非常昂贵),直到您确定它是必需的。

     

如果模块根本没有被导入(来自任何模块),这只是一个显着的节省 - 如果模块已经加载(如许多标准模块的情况,如字符串或re ),避免导入不会为你节省任何东西。要查看系统中加载了哪些模块,请参阅sys.modules。

     

进行延迟导入的好方法是:

email = None

def parse_email():
    global email
    if email is None:
        import email
  

这样,电子邮件模块只会在第一次调用parse_email()时导入一次。

答案 1 :(得分:0)

我怀疑对本地声明的函数的调用与导入的函数之间应该有区别。虽然,正在执行的代码行与要执行的相同代码调用的函数之间存在细微差别。 This如果我的措辞有点令人困惑,应该会有所帮助。