2013-04-16 3 views
26

Пусть у нас есть следующий код:Функция внутри функции - каждый раз?

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

Питон документация говорит о def заявление:

Определение функции является исполняемым оператором. Его исполнение связывает имя функции ...

Итак, вопрос: def little_function() выполнять ли каждый раз, когда big_function вызывается? Вопрос о def утверждение точно, а не little_function() тело.

ответ

30

Вы можете проверить байткод с 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, он загружается и создается новый функциональный объект (в этом смысле - это, который вызывается каждый раз, когда вызывается my_function), но это не добавляет больших накладных расходов.

+1

Как вы знаете, сколько накладных расходов выполняет команда байтового кода «MAKE_FUNCTION»? Похоже, что это может потребовать выделения памяти, которая обычно является медленной операцией на большинстве других языков. – martineau

+2

@martineau Нет, нет большого выделения памяти. Операция 'MAKE_FUNCTION' просто увеличивает ссылочный код для объекта кода, его не нужно копировать. Разумеется, создается новый функциональный объект, который включает в себя выделение нового 'PyFunctionObject', но учитывая, что * каждая операция * выделяет объект python, он значительно не влияет на производительность (очевидно, что существенно зависит от остальной части кода my_function '). – Bakuriu

+2

Отличное объяснение, спасибо! – dondublon

9

Код во внутренней функции скомпилирован только один раз, поэтому не должно быть значительного штрафа за выполнение.

Только внутренняя функция закрытие обновляется каждый раз, когда вызывается внешняя функция. См., Например, 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