在Python中,嵌套函数比全局函数快吗?

2024-09-30 18:28:29 发布

您现在位置:Python中文网/ 问答频道 /正文

我更喜欢使用嵌套函数,而不是Python中的方法或全局函数。所以我决定测试它们的性能,因为当你在另一个函数中定义一个函数时,在外部函数的每次调用中都会有内部函数定义的开销。在

充其量我希望全局函数稍微快一点,但是令人惊讶的是嵌套函数更快。有人知道为什么吗?在

这是我的代码:

from time import clock

def a(n):
    return n + 1

def b1(loopcount):
    return sum([a(n) for n in range(loopcount)])

def b2(loopcount):
    def a(n):
        return n + 1
    return sum([a(n) for n in range(loopcount)])

powers = [5, 6, 7]
b1times = []
b2times = []
print "   ", "".join(["{:^10d}".format(n) for n in powers])    
for i in range(5):
    for power in powers:
        t = clock()
        b1(10**power)
        b1times.append(clock() - t)
    for power in powers:
        t = clock()
        b2(10**power)
        b2times.append(clock() - t)
    print "b1:", "".join(["{:^10.5f}".format(n) for n in b1times])
    print "b2:", "".join(["{:^10.5f}".format(n) for n in b2times])
    print ""
    b1times = []
    b2times = [] 

这是我电脑上的结果:

^{pr2}$

更新:使用@Janne Karila的评论

现在我再叫b1和b2了,b1变快了。因此,正如@Kos和@Pavel anosov在他们的回答中所说的,有几个因素会影响这里的速度,你不能做一般性的陈述。
谢谢大家!在

from time import *

def a1(n):
    return n + 1

def b1(n):
    return a1(n)

def b2(n):
    def a2():
        return n + 1
    return a2()

powers = [4, 5, 6]
b1times = []
b2times = []
print "   ", "".join(["{:^10d}".format(n) for n in powers])    
for i in range(5):
    for power in powers:
        t = clock()
        sum([b1(n) for n in range(10**power)])
        b1times.append(clock() - t)
    for power in powers:
        t = clock()
        sum([b2(n) for n in range(10**power)])
        b2times.append(clock() - t)
    print "b1:", "".join(["{:^10.5f}".format(n) for n in b1times])
    print "b2:", "".join(["{:^10.5f}".format(n) for n in b2times])
    print ""
    b1times = []
    b2times = [] 

Tags: 函数inforreturndefrangeb2b1
3条回答

一般来说,不,因为每次运行外部函数时,都必须重新定义内部函数。在

这就是说,性能真的不重要,除非你能证明它是(例如,一个特定的循环太慢,导致性能问题)-所以我建议使用可读性最好的-过早的优化是一件坏事。在

也就是说,我认为全局函数可能是一个更好的解决方案,因为它们更容易在代码中重用,而且我要说更具可读性——毕竟,平面比嵌套好。在

这里有几个部分起作用:

1)定义函数的时间(创建函数对象),
2) 按名称查找函数对象的时间,
3) 实际调用函数的时间。在

全局函数示例使用1)(不需要在每次调用b1时重新定义a)。但是,使用in2)时的速度较慢,因为全局变量查找比局部查找慢。在

为什么我们不能两者兼得?在

我的extended your benchmark解决方案使用全局函数,但避免使用局部变量进行全局查找。它似乎是我机器上三种速度中最快的一种:

        5         6         7
b1:  0.04147   0.44421   4.46508
b2:  0.03399   0.43321   4.41121
b3:  0.03258   0.41821   4.25542

b1:  0.03240   0.42998   4.39774
b2:  0.03320   0.43465   4.42229
b3:  0.03155   0.42109   4.23669

b1:  0.03273   0.43321   4.37266
b2:  0.03326   0.43551   4.42208
b3:  0.03137   0.42356   4.25341

b1:  0.03253   0.43104   4.40466
b2:  0.03401   0.43719   4.42996
b3:  0.03155   0.41681   4.24132

b1:  0.03244   0.42965   4.37192
b2:  0.03310   0.43629   4.42727
b3:  0.03117   0.41701   4.23932

全局加载比快速加载慢得多。在

地下一层

  5           0 LOAD_GLOBAL              0 (sum)
              3 BUILD_LIST               0
              6 LOAD_GLOBAL              1 (range)
              9 LOAD_FAST                0 (loopcount)
             12 CALL_FUNCTION            1
             15 GET_ITER
        >>   16 FOR_ITER                18 (to 37)
             19 STORE_FAST               1 (n)
             22 LOAD_GLOBAL              2 (a)
             25 LOAD_FAST                1 (n)
             28 CALL_FUNCTION            1
             31 LIST_APPEND              2
             34 JUMP_ABSOLUTE           16
        >>   37 CALL_FUNCTION            1
             40 RETURN_VALUE

b2

^{pr2}$

这种差异是否弥补了每次创建函数的不足,这取决于函数(以及使用LOAD_GLOBAL的次数)。在

创建全局函数的局部引用以在内部循环中使用是一种相对常见的优化:

def a(n):
    return n + 1

def b1(loopcount):
    local_a = a
    return sum([local_a(n) for n in range(loopcount)])

这应该仍然比查找全局更快,并且比嵌套函数更易于维护。在

相关问题 更多 >