Refactoring zur Beseitigung der globalen Variablen in rekursiver Funktion

Zusammenfassend

Ich schaffe eine Baumstruktur aus einer Textdateieingabe mit einer Funktion aus SO Frage: Python-Datei-Parsing: Build-Baum aus Textdatei . Aber ich bin in der Lage, meinen Baum nur durch eine globale Variable zu produzieren und kann nicht finden, eine Möglichkeit, dies zu vermeiden.

Eingabedaten

In einer Datei namens data.txt ich folgendes:

 Root -A 10 -B --BA 2 --BB 5 --BZ 9 --BX ---X 4 ---Y ----Y0 67 ----Y1 32 ---Z 3 -C 19 

Erwünschtes Ergebnis

 {'B': ['BA 2', 'BB 5', 'BZ 9', 'B X'], 'B X': ['X 4', 'Y', 'Z 3'], 'Root': ['A 10', 'B', 'C 19'], 'Y': ['Y0 67', 'Y1 32']} 

Mein Code

 import re, pprint PATTERN = re.compile('^[-]+') tree = {} def _recurse_tree(parent, depth, source): last_line = source.readline().rstrip() while last_line: if last_line.startswith('-'): tabs = len( re.match(PATTERN, last_line).group() ) else: tabs = 0 if tabs < depth: break node = re.sub(PATTERN, '', last_line.strip()) if tabs >= depth: if parent is not None: print "%s: %s" %(parent, node) if parent in tree: tree[parent].append(node) else: tree[parent] = [ node, ] last_line = _recurse_tree(node, tabs+1, source) return last_line def main(): inFile = open("data.txt") _recurse_tree(None, 0, inFile) pprint.pprint(tree) if __name__ == "__main__": main() 

Das Problem

Wie kann ich den globalen Variablenbaum loswerden? Alles, was ich tue, scheint den Code viel länger oder hässlicher zu machen, aber ich möchte die Funktion schwer nutzen und ich hasse je nach Nebenwirkungen für das Kernergebnis.

Ergänzen

Nach den Antworten unten, überarbeitete ich den Code, um den tree auf die folgende Weise zurückzugeben. Ist das pythonisch? Ein Tupel zurückzugeben und dann das erste Element zu werfen, erscheint unelegant.

 def _recurse_tree(parent, depth, source, tree=None): if tree is None: tree = {} last_line = source.readline().rstrip() while last_line: if last_line.startswith('-'): tabs = len( re.match(PATTERN, last_line).group() ) else: tabs = 0 if tabs < depth: break node = re.sub(PATTERN, '', last_line.strip()) if tabs >= depth: if parent is not None: print "%s: %s" %(parent, node) if parent in tree: tree[parent].append(node) else: tree[parent] = [ node, ] last_line, tree = _recurse_tree(node, tabs+1, source, tree) return last_line, tree def main(): inFile = open("data.txt") tmp, tree = _recurse_tree(None, 0, inFile) pprint.pprint(tree) 

3 Solutions collect form web for “Refactoring zur Beseitigung der globalen Variablen in rekursiver Funktion”

Dein Baumvariable ist schon veränderlich; Gib es einfach mit deinen rekursiven Anrufen weiter:

 def _recurse_tree(parent, depth, source, tree=None): if tree is None: tree = {} last_line = source.readline().rstrip() while last_line: if last_line.startswith('-'): tabs = len( re.match(PATTERN, last_line).group() ) else: tabs = 0 if tabs < depth: break node = re.sub(PATTERN, '', last_line.strip()) if tabs >= depth: if parent is not None: print "%s: %s" %(parent, node) if parent in tree: tree[parent].append(node) else: tree[parent] = [ node, ] last_line = _recurse_tree(node, tabs+1, source, tree) return last_line 

Alternativ können Sie eine Klasse verwenden, um den Zustand zu halten, wird es einfacher sein, dann den Zustand aus der Instanz zu pflücken:

 class TreeBuilder(object): _PATTERN = re.compile('^[-]+') def __init__(self, source): self.tree = {} self.source = source self._recurse_tree() def _recurse_tree(self, parent=None, depth=0): last_line = self.source.readline().rstrip() while last_line: if last_line.startswith('-'): tabs = len( self._PATTERN.match(last_line).group() ) else: tabs = 0 if tabs < depth: break node = self._PATTERN.sub('', last_line.strip()) if tabs >= depth: if parent is not None: print "%s: %s" %(parent, node) if parent in self.tree: self.tree[parent].append(node) else: self.tree[parent] = [ node, ] last_line = self._recurse_tree(node, tabs+1) return last_line 

Dann benutze das so:

 def main(): inFile = open("data.txt") builder = TreeBuilder(inFile) pprint.pprint(builder.tree) 

Ich denke, gute Lösung hier – schaffen Klasse und setzen Baum innen, wie ein privates Klassenmitglied.

Oder Sie können dieses Wörterbuch einfach als einen der Parameter in der Funktion übergeben und es während der Rekursion übergeben. Es wird durch Verweis übergeben, also wird die ganze Zeitfunktion das gleiche Wörterbuch ohne globale Variable verwenden. Aber ich würde lieber Klasse.

Verwenden Sie tree als Standardparameter in Ihrer Funktion: –

 def _recurse_tree(parent, depth, source, tree = None): if tree is None: # needed on first invocation tree = {} 

Nennen Sie es zum ersten Mal ohne tree und fügen Sie bei jedem aufeinanderfolgenden Aufruf einen weiteren Parameterbaum hinzu.

Also, von innen Ihre Methode wird Ihr rekursiver Anruf: –

 last_line = _recurse_tree(node, tabs+1, source, tree) 
  • Rekursiv finden Sie alle Münzkombinationen, die eine bestimmte Menge produzieren
  • Kreuz Produkt von Sets mit Rekursion
  • Rekursive Funktion, die keine zurückgibt?
  • Berechnungsdeterminante einer Matrix (nxn) rekursiv
  • Rekursive Funktion gibt keine in Python zurück [doppelte]
  • N-Queen-Backtracking in Python: Wie gibt man Lösungen zurück, anstatt sie zu drucken?
  • Python max Rekursion, Frage über sys.setrecursionlimit ()
  • Refactoring rekursive "Vorkommen von" Funktion
  • Python rekursiver Funktionsfehler: "maximale Rekursionstiefe überschritten"
  • Python Recursive Funktion fehlende Ergebnisse
  • Ist diese Funktion rekursiv, obwohl sie sich nicht nennt?
  • Python ist die beste Programmiersprache der Welt.