Seite 1 von 1

rekursiver Aufruf innerhalb einer Klasse

Verfasst: Dienstag 18. April 2017, 08:55
von Sanne1612
Hallo liebes Forum,

ich möchte gerne eine Baumstruktur mittels Python implementieren und alle Funktionen in einer Klasse bündeln.
Nun gibt es aber scheinbar ein Problem mit der Rekursivität der Struktur. Die Initialisierung ist geläufig.
Jetzt soll die Funktion gesamt() Die Summe der einzelnen Blätter errechnen.

Code: Alles auswählen

class Baum(object):
    """ Klasse für eine einfache Baumstruktur """

    def __init__(self, value, left = None, right = None):
        """ Neuen Knoten des Baumes initialisieren """
        self.left = left
        self.right = right
        self.value = value
     
     def gesamt(self):
        if self == None: return 0
        return self.left.gesamt() + self.right.gesamt() + self.value
        
if __name__ == "__main__":
    baum = Baum(1, Baum(2), Baum(3))
    print baum.gesamt()
Fehlermeldung: AttributeError: 'NoneType' object has no attribute 'gesamt'

Ich scheine an irgendeiner Stelle einen Denkfehler zu haben. Kann mir jemand weiterhelfen?

Beste Grüße Sanne

Re: rekursiver Aufruf innerhalb einer Klasse

Verfasst: Dienstag 18. April 2017, 09:12
von Liffi
self.left oder self.right können None sein, du prüfst ja nur auf self.

Noch ein Tipp: Eine Prüfung auf None sollte man mit 'is' machen, nicht per '=='.

Re: rekursiver Aufruf innerhalb einer Klasse

Verfasst: Dienstag 18. April 2017, 09:37
von BlackJack
@Sanne1612: `self` auf `None` zu prüfen macht auch gar keinen Sinn weil `self` nie `None` sein dürfte. Denn das würde ja bedeuten man hätte die `gesamt()`-Methode eines `None`-Objekts aufgerufen und nicht die eines `Baum`-Objekts. Und `None`-Objekte haben gar keine `gesamt()`-Methode. Wie die Fehlermeldung ja auch sehr deutlich sagt. :-)

Re: rekursiver Aufruf innerhalb einer Klasse

Verfasst: Dienstag 18. April 2017, 11:21
von kbr
@Sanne1612: Deine Methode gesamt() scheint aus Gefühl geschrieben zu sein. Sie müsste wie folgt lauten:

Code: Alles auswählen

    def gesamt(self):
        result = self.value
        if self.left:
            result += self.left.gesamt()
        if self.right:
            result += self.right.gesamt()
        return result
Versuche zu erklären, was hier Zeile für Zeile geschieht.

Re: rekursiver Aufruf innerhalb einer Klasse

Verfasst: Dienstag 18. April 2017, 11:37
von Sanne1612
Dann wäre das die Lösung?

Code: Alles auswählen

def gesamt(self):
        if self is None: return 0
        if self.left is not None and self.right is not None:
            return self.left.gesamt() + self.right.gesamt() + self.value
Schmeißt mir nun einen Typfehler:
TypeError: unsupported operand type(s) for +: 'NoneType' and 'NoneType'

Was ich nicht ganz verstehe ist, warum die Funktion:

Code: Alles auswählen

def gesamt(baum): 
   if baum == None: return 0 
   return gesamt(baum.links) + gesamt(baum.rechts) + baum.inhalt
außerhalb der Klasse definiert fehlerlos funktioniert und in der Klasse integriert nicht.

Liebe Grüße Sanne

Re: rekursiver Aufruf innerhalb einer Klasse

Verfasst: Dienstag 18. April 2017, 11:43
von BlackJack
@Sanne1612: Weil auf der Klasse als Methode definiert `self`, wie schon gesagt, niemals `None` ist und die Methode nur auf `Baum` definiert ist, aber nicht auf `None`. Du versuchst aber die Methode `gesamt()` auf `None`-Objekten aufzurufen. Und dort gibt's die halt nicht.

Edit: Zum neuen Versuch: Du prüfst ob `left` und `right` nicht `None` sind. Das ist aber nicht der einzige Fall der auftreten kann. Und was passiert wenn die Bedingung nicht erfüllt ist? Was denkst Du was die Methode dann zurück gibt?

Re: rekursiver Aufruf innerhalb einer Klasse

Verfasst: Dienstag 18. April 2017, 11:47
von Sirius3
@Sanne1612: Deine neue Lösung berücksichtigt die Fälle, dass left und/oder right None sind nicht. Was wird in diesen Fällen zurückgegeben?

Re: rekursiver Aufruf innerhalb einer Klasse

Verfasst: Dienstag 18. April 2017, 11:52
von Sanne1612
Er hatte bei mir noch nicht die neuen Forumbeiträge geladen, daher ging das etwas durcheinander.
Ich habe es nun grundsätzlich verstanden und versuche die weiteren Funktionen, wie einfügen etc.
abzuleiten.

Vielen Dank für die Unterstützung,
Sanne