@beQSwa: `obj` ist kein guter Name für eine Klasse. Zum einen erkennt man nicht, das es eine Klasse ist, denn Klassennamen werden in Python per Konventionen in PascalCase geschrieben, das heisst die Worte aus denen der Name zusammengesetzt ist, beginnen mit Grossbuchstaben. Aber auch `Obj` wäre nicht gut, weil a) kryptische Abkürzung und b) absolut nichtssagend. Dieser Wert wird im Kontext von Bäumen in der Regel „Knoten“, oder englisch „node“ genannt, also als Klasse dann `Node`.
Veränderbare Objekte als Defaultwerte sind gefährlich, weil es den Wert nur *einmal* gibt. Das ist bei jeden Aufruf das *selbe* Objekt, und bei Klassen dann auch noch für jedes Exemplar:
Code: Alles auswählen
In [3]: class Node:
...: def __init__(self, name, children=[]):
...: self.name = name
...: self.children = children
...:
In [4]: node_a = Node("A")
In [5]: node_a.children
Out[5]: []
In [6]: node_b = Node("B")
In [7]: node_b.children
Out[7]: []
In [8]: node_a.children.append(Node("C"))
In [9]: node_a.children
Out[9]: [<__main__.Node at 0x7f9f59a4f3c8>]
In [10]: node_b.children # Ooops.
Out[10]: [<__main__.Node at 0x7f9f59a4f3c8>]
Die übliche Lösung ist `None` als Defaultwert zu setzen und in der Funktion oder Methode dann darauf zu testen und gegebenfalls das `None` durch ein neu erstelltes Objekt zu ersetzen.
`nextchild()` ist kein guter Name denn die macht ja nicht nur etwas mit dem nächsten Kindknoten, und es wird auch gar nicht verraten *was* gemacht wird.
Um die Bedingung bei ``if`` gehören keine Klammern.
Ein bedingungsloses ``return`` in einer Schleife macht keinen Sinn, denn dann ist das letztlich ja gar keine Schleife, denn bei einer Schleife die nur genau einmal durchlaufen wird, kann man nicht wirklich von einer Schleife sprechen.
Zudem sollte einfach Funktion mit ``return`` in *jedem* Zweig etwas zurückgeben.
Statt alles in dieser Funktion zu lösen, wäre es einfacher dort nur die Pfadinformationen zu generieren und das Speichern ausserhalb zu machen. Die Pfadinformationen als Listen, weil man die dann einfach an ein Writer-Objekt aus dem `csv`-Modul verfüttern kann um Daten im CSV-Format zu erstellen. Es bietet sich auch eine Generatorfunktion an, statt erst alle Daten in einer weiteren Liste zu sammeln und die bei jedem rekursiven Aufruf durchzureichen.
Quelltext:
Code: Alles auswählen
#!/usr/bin/env python3
import csv
import sys
class Node:
def __init__(self, name, children=None):
if children is None:
children = []
self.name = name
self.children = children
def iter_paths(node, path=None):
path = [node.name] if path is None else path + [node.name]
yield path
for child in node.children:
yield from iter_paths(child, path)
def main():
tree = Node("A", [Node("B", [Node("D"), Node("E"), Node("F")]), Node("C")])
csv.writer(sys.stdout).writerows(iter_paths(tree))
if __name__ == "__main__":
main()
Ausgabe:
Entspricht nicht der Ausgabe im Kommentar, weil sich auch die Struktur des Baums im Code von der im Kommentar unterscheidet.