您可以使用闭包来优化函数中的导入吗?

时间:2017-01-05 15:31:42

标签: python closures python-import

These two问题涉及在函数内使用import而在模块顶部使用import sys def get_version(): return sys.version 。我不需要被说服将我的进口放在首位,这是有充分理由的。但是,为了更好地理解技术问题,我想问一下后续行动。

通过使用闭包并仅在首次运行函数时导入,你能否在性能方面获得最佳效果?

具体来说,假设您有以下代码:

def get_version():
    import sys
    return sys.version

您希望仅在调用该函数时才进行导入,因此您将其移入:

def _get_version():
    import sys

    def nested():
        return sys.version

    global get_version
    get_version = nested
    return nested()
get_version = _get_version

但是现在它很慢,如果 被调用很多,所以你尝试更复杂的东西:

SELECT id_slider,id_multimedia,path_m FROM slider JOIN slider_immagini ON slider.id = id_slider JOIN multimedia ON id_multimedia = multimedia.id WHERE slider.id_utente = ='" . $user_landing . "' ORDER BY data_creazione ASC

现在至少有一个基本的性能测试表明最后一个选项比第一个选项略慢(大约需要110%),但比第二个快得多(大约需要20%)。

首先,这确实有效吗?我的测量结果是否准确地描述了第二个例子做了更多的工作,或者它是我测量事物的方法。

第二,关闭时是否会减速 - 超出第一次运行该功能?

1 个答案:

答案 0 :(得分:3)

关闭解除引用并不比全局查找更快:

>>> import sys
>>> sys.version_info
sys.version_info(major=3, minor=6, micro=0, releaselevel='final', serial=0)
>>> from timeit import timeit
>>> glob = 'foo'
>>> def f1(): return glob
...
>>> def closure():
...     closed_over = 'bar'
...     def f2():
...         return closed_over
...     return f2
...
>>> f2 = closure()
>>> timeit(f1, number=10**7)
0.8623221110319719
>>> timeit(f2, number=10**7)
0.872071701916866

此外,即使 更快,但是对可读性的权衡也是不值得的,当你真正需要优化代码时,当你有更快的选择时,肯定不会这样做。

本地是最快的选择,如果你真的需要优化从紧密循环调用的代码,那么正确的混合使用函数参数默认值:

import sys.version

def get_version(_sys_version=sys.version):
    return _sys_version

如果您担心启动时导入的初始文件加载的影响,也许您应该查看py-demandimport project,这会延迟加载模块,直到它们第一次使用。