2016-04-14 12 views
1

Mit den ast und astor Bibliotheken, ich habe ein einfaches Skript geschrieben, das eine AST alle leeren Listen mit None mit ast.NodeTransformer und ersetzt durchläuft:Wie kann ich einen AST-Besucher abbrechen und den ursprünglichen Knoten unverändert lassen?

import ast 
import astor 


class ListChanger(ast.NodeTransformer): 
    def visit_List(self, node): 
     if len(node.elts) > 0: 
      return ast.copy_location(node, node) 
     return ast.copy_location(ast.NameConstant(value=None), node) 

x = ast.parse("""["A"]""") 
ListChanger().visit(x) 
print(astor.to_source(x)) 

y = ast.parse("""[]""") 
ListChanger().visit(y) 
print(astor.to_source(y)) 

Diese richtig, und Ausgänge funktionieren:

["A"] 
None 

Ich bin mir jedoch nicht sicher über die Zeile, die ich aus der Funktion gezogen habe, wenn die Liste leer ist:

return ast.copy_location(node, none) 

Wenn ich dieses durch return ersetze und das Skript None zurückgibt, wenn die Bedingung nicht erfüllt ist, wird der Knoten zerstört, anstatt unverändert gelassen zu werden. Der erste Testfall druckt eine leere Zeichenfolge, da der Knoten ast.List zerstört wurde.

Ich will nicht, dass dies passiert, aber ich denke auch, dass mit ast.copy_location(node, node) scheint falsch. Gibt es eine dedizierte Funktion, um den Knoten unverändert zu belassen und die Funktion zu verlassen oder um ast.NodeTransformer so zu konfigurieren, dass der Knoten unverändert bleibt, wenn eine visit Funktion None zurückgibt?

Antwort

1

Vom documentation:

Der Rückgabewert der ursprüngliche Knoten sein kann, wobei in diesem Fall kein Ersatz stattfindet.

Also statt:

return ast.copy_location(node, none) 

gerade:

return node 
+0

Brilliant - hätte nicht gedacht, in der Dokumentation zu suchen. Vielen Dank! –