2013-04-16 10 views
26

Lassen wir haben diesen Code:Funktion innerhalb der Funktion - jedes Mal?

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

Die Python-Dokumentation sagt über def Aussage:

Eine Funktionsdefinition eine ausführbare Anweisung ist. Seine Ausführung bindet der Name der Funktion ...

Also, die Frage ist: Hat def little_function() jedes Mal ausgeführt wird, wenn big_function aufgerufen wird? Frage ist über def Aussage genau, nicht die little_function() Körper.

Antwort

30

Sie den Bytecode mit dem dis Modul überprüfen:

>>> 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 

Wie Sie den Code für die innere Funktion sehen kann, ist kompiliert nur einmal. Jedes Mal, wenn Sie my_function aufrufen, wird es geladen und ein neues Funktionsobjekt wird erstellt (in diesem Sinne wird die def little_functionist ausgeführt jedes Mal my_function wird aufgerufen), aber dies fügt nicht viel Aufwand.

+1

Woher wissen Sie, wie viel Aufwand die Bytecode-Anweisung 'MAKE_FUNCTION' ausführt? Sieht so aus, als müsste in den meisten anderen Sprachen Speicher reserviert werden, was normalerweise eine langsame Operation ist. – martineau

+2

@martineau Nein, es gibt keine große Speicherzuweisung. Die Operation 'MAKE_FUNCTION' erhöht einfach den Referenzcode für das Codeobjekt, es muss nicht kopiert werden. Sicherlich wird ein neues Funktionsobjekt erstellt, das die Zuweisung eines neuen 'PyFunctionObject' beinhaltet, aber da * jede * Operation ein Python-Objekt zuweist, beeinträchtigt es die Performances nicht" signifikant "(offensichtlich hängt das Wesentliche vom Rest des Codes von' my_function ab '). – Bakuriu

+2

Große Erklärung, danke! – dondublon

9

Der Code in der inneren Funktion wird nur einmal kompiliert, daher sollte es keinen signifikanten Laufzeitverlust geben.

Nur innere Funktion Schließung wird jedes Mal aktualisiert, wenn die äußere Funktion aufgerufen wird. Weitere Informationen zu Verschlüssen finden Sie beispielsweise unter here.

Hier ist eine schnelle Demonstration, die Schließung der Prüfung:

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 
Verwandte Themen