5

我在某处读到,在 python 的函数内部定义函数是不好的,因为它使 python 在调用外部函数时创建一个新的函数对象。基本上有人这么说:

#bad
def f():
    def h():
        return 4
return h()

#faster
def h():
    return 4

def f(h=h):
    return h()

这是真的?另外,如果我有大量这样的常量,该怎么办:

x = # long tuple of strings
# and several more similar tuples
# which are used to build up data structures

def f(x):
    #parse x using constants above
    return parse dictionary

如果我将所有常量都放在 f 的定义中会更快吗?还是应该将它们留在外面并在关键字参数中将它们绑定到本地名称?不幸的是,我没有任何数据可用于计时,所以我想我是在询问您在类似事情上的经历。

4

3 回答 3

6

简短回答你的问题 - 这是真的。每次调用外部函数时都会创建内部函数,这需要一些时间。与访问局部变量相比,访问在函数外部定义的对象也更慢。

然而,你也问了更重要的问题——“我应该关心吗?”。几乎总是回答这个问题,。性能差异将非常小,并且代码的可读性更有价值。

所以,如果你认为这个函数属于其他函数的主体并且在其他地方没有意义 - 只需将它放在里面而不关心性能(至少,直到你的分析器告诉你否则)。

于 2013-11-03T16:08:56.960 回答
0

当一个函数被执行时,里面的所有代码都需要被执行。所以当然,很简单地说,你在函数中投入的越多,Python 执行它所花费的精力就越多。特别是当你有一些不需要在函数运行时构造的常量,你可以通过将它放在一个上层范围内来节省很多,这样 Python 只需要查找它而不是再次生成它并分配它(临时)内存以将其保存为函数的短期运行时间。

所以在你的情况下,如果你有一个大的元组或任何不依赖于x函数输入的东西f,那么是的,你应该把它存储在外面。

现在您提到的另一件事是使用关键字参数对函数或常量进行范围查找。一般来说,在外部范围内查找变量比在最本地范围内查找要昂贵。所以是的,当您在模块级别定义这些常量并在函数内部访问它们时,查找将比在函数内部定义常量时更昂贵。然而,在函数内部实际定义它们(内存分配和数据的实际生成)可能会更昂贵,所以这真的不是一个好的选择。

现在您可以将常量作为关键字参数传递给函数,因此函数内部的查找将是本地范围查找。但很多时候,你并不需要这些常量。您可能在函数中访问它一次或两次,这绝对不值得向函数添加另一个参数的开销以及向它传递不同/不兼容的东西(破坏函数)的可能性。

如果您知道您多次访问某些全局内容,则在函数顶部创建一个局部变量,该变量将全局内容查找一次,然后在所有其他地方使用该局部变量。这也适用于成员查找,这也可能很昂贵。

但总的来说,这些都是相当微的优化,如果你以一种或另一种方式去做,你不太可能遇到任何问题。所以我建议你先写清晰的代码,确保其余部分运行良好,如果你以后确实遇到性能问题,那么你可以检查问题出在哪里。

于 2013-11-03T16:11:04.073 回答
0

在我的测试中,完成我需要做的最快的方法是在外部定义我需要的所有常量,然后列出需要这些常量的函数列表,然后将函数列表传递给主函数。我使用dis.dis, cProfile.run, 和timeit.timeit进行测试,但我找不到基准测试脚本,也懒得重写它并提供结果。

于 2013-12-02T21:50:13.477 回答