函数内部的函数 - 每次?

Posted

技术标签:

【中文标题】函数内部的函数 - 每次?【英文标题】:Function inside function - every time? 【发布时间】:2013-04-08 12:09:37 【问题描述】:

让我们有这个代码:

def big_function():
    def little_function():
         .......
    .........

Python 文档中提到了def 声明:

函数定义是一个可执行语句。它的执行绑定 函数名...

所以,问题是: def little_function() 每次调用big_function 时都会执行吗? 问题是关于 def 声明,而不是 little_function() 正文。

【问题讨论】:

【参考方案1】:

内部函数中的代码只编译一次,因此不会有显着的运行时损失。

每次调用外部函数时,只有内部函数 closure 会更新。例如,请参阅here,了解有关闭包的更多详细信息。

这是一个快速演示,检查闭包:

def f(x):
   a = []
   b = x + 1
   def g():
      print a, b
   return g

In [28]: y = f(5)

In [29]: y
Out[29]: <function __main__.g>

In [30]: y.func_closure
Out[30]: 
(<cell at 0x101c95948: list object at 0x101c3a3f8>,
 <cell at 0x101c958a0: int object at 0x100311aa0>)

In [31]: y.func_closure[1].cell_contents
Out[31]: 6

【讨论】:

【参考方案2】:

您可以使用dis 模块检查字节码:

>>> import dis
>>> def my_function():
...     def little_function():
...             print "Hello, World!"
...     
... 
>>> dis.dis(my_function)
  2           0 LOAD_CONST               1 (<code object little_function at 0xb74ef9f8, file "<stdin>", line 2>)
              3 MAKE_FUNCTION            0
              6 STORE_FAST               0 (little_function)
              9 LOAD_CONST               0 (None)
             12 RETURN_VALUE  

如您所见,内部函数的代码只编译一次。每次调用 my_function 时它都会被加载并创建一个新的函数对象(在这个意义上,def little_function is 每次调用 my_function 时都会执行),但这并没有增加太多开销。

【讨论】:

你怎么知道执行MAKE_FUNCTION字节码指令涉及多少开销?似乎它可能需要分配内存,这在大多数其他语言中通常是一个缓慢的操作。 @martineau 不,没有大的内存分配。 MAKE_FUNCTION 操作只是增加了代码对象的参考代码,它不必复制。肯定会创建一个新的函数对象,这涉及分配一个新的PyFunctionObject,但考虑到 每个 操作都会分配 python 对象,它不会“显着”损害性能(显然,重要的是取决于其余的my_function的代码)。

以上是关于函数内部的函数 - 每次?的主要内容,如果未能解决你的问题,请参考以下文章

Python之闭包

无法访问函数内部的状态

PHP include/require 内部函数

Knockout observable 在函数内部不可访问

js里面函数的内部属性

Azure 函数状态码 500 内部服务器错误