Python - 导入函数和本地声明它之间的性能差异? [英] Python - Performance difference between importing a function and locally declaring it?

查看:49
本文介绍了Python - 导入函数和本地声明它之间的性能差异?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

解决方案

Hi Jet Blue 为了更好地理解使用 python wiki 性能提示

<块引用>

import 语句几乎可以在任何地方执行.将它们放在函数内部以限制它们的可见性和/或减少初始启动时间通常很有用.尽管 Python 的解释器已优化为不会多次导入同一个模块,但在某些情况下重复执行导入语句会严重影响性能.

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

>

def doit1():导入字符串###### 函数内的导入语句string.lower('Python')对于范围内的数量(100000):doit1()

<块引用>

或:

import string ######import 语句外函数def doit2():string.lower('Python')对于范围内的数量(100000):doit2()

<块引用>

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

def doit1():导入字符串string.lower('Python')导入字符串def doit2():string.lower('Python')导入时间t = timeit.Timer(setup='from __main__ import doit1', stmt='doit1()')t.timeit()11.479144930839539t = timeit.Timer(setup='from __main__ import doit2', stmt='doit2()')t.timeit()4.6661689281463623

<块引用>

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

def doit3():'Python'.lower()对于范围内的数量(100000):doit3()

<块引用>

这是来自 timeit 的证明:

定义 doit3():'Python'.lower()

t = timeit.Timer(setup='from ma​​in import doit3', stmt='doit3()')t.timeit()2.5606080293655396

<块引用>

上面的例子显然有点做作,但大体原理是成立的.

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

这只是在模块根本没有导入(从任何模块)的情况下显着的节省——如果模块已经加载(对于许多标准模块,如 string 或 re),避免导入不会为您节省任何东西.要查看系统中加载了哪些模块,请查看 sys.modules.

延迟导入的一个好方法是:

email = 无def parse_email():全球电子邮件如果电子邮件是无:导入电子邮件

<块引用>

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

Is there a significant difference in performance between importing a function versus declaring it in the current file in Python?

I have a small function (one-liner) that I use often in several .py files in my program. I wish to instead define it once so that changes I make to it are reflected everywhere. However, I am not sure whether using it as an imported function will add additional overhead when calling it...

解决方案

Hi Jet Blue for better understanding go with the python wiki PerformanceTips

import statements can be executed just about anywhere. It's often useful to place them inside functions to restrict their visibility and/or reduce initial startup time. Although Python's interpreter is optimized to not import the same module multiple times, repeatedly executing an import statement can seriously affect performance in some circumstances.

Consider the following two snippets of code (originally from Greg McFarlane, I believe - I found it unattributed in a comp.lang.python python-list@python.org posting and later attributed to him in another source):

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

for num in range(100000):
    doit1()

or:

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

for num in range(100000):
    doit2()

doit2 will run much faster than doit1, even though the reference to the string module is global in doit2. Here's a Python interpreter session run using Python 2.3 and the new timeit module, which shows how much faster the second is than the first:

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

String methods were introduced to the language in Python 2.0. These provide a version that avoids the import completely and runs even faster:

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

for num in range(100000):
    doit3()

Here's the proof from timeit:

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

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

The above example is obviously a bit contrived, but the general principle holds.

Note that putting an import in a function can speed up the initial loading of the module, especially if the imported module might not be required. This is generally a case of a "lazy" optimization -- avoiding work (importing a module, which can be very expensive) until you are sure it is required.

This is only a significant saving in cases where the module wouldn't have been imported at all (from any module) -- if the module is already loaded (as will be the case for many standard modules, like string or re), avoiding an import doesn't save you anything. To see what modules are loaded in the system look in sys.modules.

A good way to do lazy imports is:

email = None

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

This way the email module will only be imported once, on the first invocation of parse_email().

这篇关于Python - 导入函数和本地声明它之间的性能差异?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆