2010-09-02 15 views
10

I einen kleinen Schnipsel geschrieben habe, die die Pfadlänge eines gegebenes Knotens (zB seine Entfernung zu dem Wurzelknoten) Berechnet:Python: Ungewöhnliches Verhalten der rekursiven Funktion mit Argumenten Schlüsselwort

def node_depth(node, depth=0, colored_nodes=set()): 
    """ 
    Return the length of the path in the parse tree from C{node}'s position 
    up to the root node. Effectively tests if C{node} is inside a circle 
    and, if so, returns -1. 

    """ 
    if node.mother is None: 
     return depth 
    mother = node.mother 
    if mother.id in colored_nodes: 
     return -1 
    colored_nodes.add(node.id) 
    return node_depth(mother, depth + 1, colored_nodes) 

Nun gibt es eine Seltsames, was mit dieser Funktion passiert (zumindest ist es mir seltsam): Der Aufruf von node_depth liefert zum ersten Mal den richtigen Wert zurück. Wenn Sie es jedoch ein zweites Mal mit demselben Knoten aufrufen, wird -1 zurückgegeben. Die colored_nodes gesetzt ist leer im ersten Aufruf, sondern enthält alle Knoten-IDs in dem zweiten Aufruf, die während der ersten hinzugefügt wurden:

print node_depth(node) # --> 9 
# initially colored nodes --> set([]) 
print node_depth(node) # --> -1 
# initially colored nodes --> set([1, 2, 3, 38, 39, 21, 22, 23, 24]) 

print node_depth(node, colored_nodes=set()) # --> 9 
print node_depth(node, colored_nodes=set()) # --> 9 

Bin ich einige Python-spezifische Sache hier fehlt und das ist wirklich soll sei auch so?

Vielen Dank im Voraus,

Jena

+0

Die gleiche Sache beißen mich und ich fand Ihre Frage und eine weitere SO der Detailerklärung. http://stackoverflow.com/questions/1132941/least-astonishment-in-python-which-scope-is-the-mutable-default-argument-in – Yefei

Antwort

15

Der „Standardwert“ für einen Funktionsparameter in Python zu Funktionsdeklaration Zeit instanziert wird, nicht jedes Mal wird die Funktion aufgerufen. Sie möchten nur selten den Standardwert eines Parameters ändern, und daher ist es oft eine gute Idee, etwas zu verwenden, das für den Standardwert unveränderlich ist.

In Ihrem Fall können Sie so etwas wie dies tun wollen:

def node_depth(node, depth=0, colored_nodes=None): 
    ... 
    if colored_nodes is None: colored_nodes = set() 
+0

Das ist eine gute Sache zu wissen - vielen Dank. (Und da jemand fragte: Nein, das ist keine Hausaufgaben.) – jena

+0

Danke dafür! Tolles Trinkgeld. @jena: Danke, dass du das auch gefragt hast. :) – hayavuk

6

Dies ist, weil in Python, die Standard-Argument Werte sind nicht ausgewertet jedes Mal die Funktion aufgerufen wird, aber nur einmal an Funktionsdefinitionszeit. So effektiv, rufen Sie die Funktion mit einem vorgefüllten colored_nodes bei jedem außer dem ersten Anruf nach der Definition festgelegt.

+0

Danke, ich habe etwas gelernt. Jetzt ist mein Tag abgeschlossen. – wheaties

Verwandte Themen