在另一个函数定义内部定义函数——速度慢?

9

来看一下两种组织函数的方式:

class myClass:
    def _myFunc(self):
        pass

    def myFunc2(self):
        self._myFunc()

class myClass:
    def myFunc2(self):
        def myFunc():
            pass

        myFunc()

第二个选项会更慢吗? 我只需要从myFunc2调用myFunc,所以我想将其隐藏在我的模块文档中,我可以使用下划线来代替,但我认为将其放置在函数内部会更清晰。另一方面,我可能需要每秒调用myFunc2几百次,因此在每次调用myFunc2时“重新定义”myFunc可能会很慢...这是一个好的猜测吗?

我能想到的唯一区别可能与全局变量有关,但由于整个事情都包装在一个类中,这不是问题。 - Katriel
4个回答

8

在64位Ubuntu上使用Python 2.6.5,没有明显的差异:

# version 1
In [2]: %timeit c1.myFunc2()
1000000 loops, best of 3: 461 ns per loop

# version 2
In [3]: %timeit c2.myFunc2()
1000000 loops, best of 3: 464 ns per loop

4
第二种方法中的本地函数不会反复编译 - 它与整个文件一起编译一次,其主体存储在代码对象中。在执行外部函数期间唯一发生的事情是将代码对象包装在一个新的函数对象中,然后将其绑定到本地名称myFunc
如果myFunc()具有默认参数,则两种变体之间可能存在差异。在第二种变体中,它们的定义将被反复执行,从而可能导致性能下降。
夸张的例子:
from time import sleep

class MyClass:
    def _my_func(self, x=sleep(1)):
        pass
    def my_func2(self):
        self._my_func()

class MyClass2:
    def my_func2(self):
        def my_func(x=sleep(1)):
            pass
        my_func()

使用上述代码,myClass.myFunc2()会立即返回结果,而myClass2.myFunc2()需要一秒钟才能执行。

我不太明白为什么 myClass2.myFunc2() 要花费一秒钟,而 myClass.myFunc2() 立即返回。如果 myFunc() 使用默认参数,为什么第二种情况下定义会一遍又一遍地执行? - Alcott
1
@Alcott:默认参数在函数定义的时候被计算。第二种变量因为在my_func2()内部,所以会不断地执行函数定义。而第一种变量只会执行一次函数定义。 - Sven Marnach
那么我认为, myClass.myFunc2() 应该需要 1 秒才能执行,而 myClass2.myFunc2() 则需要 2 秒? - Alcott

2
点式查找(也称属性绑定)比嵌套的范围查找要耗时更长。前者涉及一系列字典查找和创建一个新对象(绑定或非绑定方法)。后者使用单元格变量,并使用数组查找实现。

0

尽管其他答案声称没有影响,但我认为我应该检查一下。 我发现在函数外定义函数有一个非常明显的优点。

import random
def ff1(i):
    r1 = random.random()
    r2 = random.random()
    if r1 < 0.5:
        return i*r2
    else:
        return i/r2

def f1(i):
    return ff1(i)

def f2(i):
    def ff2(i):
        r1 = random.random()
        r2 = random.random()
        if r1 < 0.5:
            return i*r2
        else:
            return i/r2
    return ff2(i)

%%timeit -r 10 -n 10 
x = 0.5
for i in xrange(10000):
    x = f1(x)

10次循环,取最佳结果10次:每次循环4.2毫秒

%%timeit -r 10 -n 10
x = 0.5
for i in xrange(10000):
    x = f2(x)

10次循环,取最佳结果10次:每次循环5.33毫秒

%%timeit -r 1 -n 1 
x = 0.5
for i in xrange(1000000):
    x = f1(x)

1次循环,最佳1次:每次循环438毫秒

%%timeit -r 1 -n 1
x = 0.5
for i in xrange(1000000):
    x = f2(x)

1 次循环,最佳结果为 1 次:每次循环 574 毫秒


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接