在Python中嵌套函数时是否有开销?
在Python中,如果在父函数中有一个子函数,那么每次调用父函数时,子函数是否被“初始化”(创build)? 在另一个嵌套函数中是否有任何开销?
是的,每次都会创build一个新的对象。 这可能不是一个问题,除非你有一个紧密的循环。 分析会告诉你是否有问题。
In [80]: def foo(): ....: def bar(): ....: pass ....: return bar ....: In [81]: id(foo()) Out[81]: 29654024 In [82]: id(foo()) Out[82]: 29651384
代码对象是预编译的,所以部分没有开销。 函数对象在每次调用时都被构build – 它将函数名绑定到代码对象,logging默认variables等。
执行摘要:这不是免费的。
>>> from dis import dis >>> def foo(): def bar(): pass return bar >>> dis(foo) 2 0 LOAD_CONST 1 (<code object bar at 0x1017e2b30, file "<pyshell#5>", line 2>) 3 MAKE_FUNCTION 0 6 STORE_FAST 0 (bar) 4 9 LOAD_FAST 0 (bar) 12 RETURN_VALUE
有一个影响,但在大多数情况下,它是如此之小,你不应该担心它 – 大多数不平凡的应用程序可能已经有性能瓶颈,其影响比这个大几个数量级。 担心代码的可读性和可重用性。
这里有一些代码,比较每次重新定义一个函数通过循环重用预定义函数的性能。
import gc from datetime import datetime class StopWatch: def __init__(self, name): self.name = name def __enter__(self): gc.collect() self.start = datetime.now() def __exit__(self, type, value, traceback): elapsed = datetime.now()-self.start print '** Test "%s" took %s **' % (self.name, elapsed) def foo(): def bar(): pass return bar def bar2(): pass def foo2(): return bar2 num_iterations = 1000000 with StopWatch('FunctionDefinedEachTime') as sw: result_foo = [foo() for i in range(num_iterations)] with StopWatch('FunctionDefinedOnce') as sw: result_foo2 = [foo2() for i in range(num_iterations)]
当我在运行OS X Lion的Macbook Air上运行Python 2.7时,得到:
** Test "FunctionDefinedEachTime" took 0:00:01.138531 ** ** Test "FunctionDefinedOnce" took 0:00:00.270347 **
其他答案很好,真的很好地回答了这个问题。 我想补充说,大多数内部函数可以避免在python中使用循环,生成函数等。
考虑下面的例子:
def foo(): # I need to execute some function on two sets of arguments: argSet1 = (arg1, arg2, arg3, arg4) argSet2 = (arg1, arg2, arg3, arg4) # A Function could be executed on each set of args def bar(arg1, arg2, arg3, arg4): return (arg1 + arg2 + arg3 + arg4) total = bar(argSet1) total += bar(argSet2) # Or a loop could be used on the argument sets total = 0 for arg1, arg2, arg3, arg4 in [argSet1, argSet2]: total += arg1 + arg2 + arg3 + arg4
这个例子有点愚蠢,但是我希望你能看到我的观点。 内部function通常是不需要的。