OOP

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
d_rose
User
Beiträge: 57
Registriert: Dienstag 30. Oktober 2018, 11:34

Hallo, ich weis ich weis der folgende Code ist sehr unnötig dafür was er machen soll aber das Buch durch das ich mich arbeite gerade nutzt diese billigen Beispiele um einfach die Konzepte der OOP zu erklären.
Allerdings scheint der bei mir nicht zu funktionieren, Tippfehler sollten keine vorhanden sein.
Ich bekomme den Error :"TypeError : ">" not supported between instances of "Fahrzeug" and "Fahrzeug".
Eigentlich sollte die Ausgabe sein : "Opel ist schneller" und "Geschwindigkeitsdifferenz : 15 km/h".

Wäre euch sehr dankbar falls man mir aufzeigt wo der Haken ist. Arbeite mit Python 3.7.1 falls das nötig ist zu wissen.

Code: Alles auswählen

class Fahrzeug :
        def __init__(self, bez, ge):
                self.bezeichnung = bez
                self.geschwindigkeit = ge
                def __gt__(self,other):
                        return self.geschwindigkeit > other.geschwindigkeit
                def __eq__ (self,other) :
                        return self.geschwindigkeit == other.geschwindigkeit
                def __sub__ (self,other):
                        return self.geschwindigkeit - other.geschwindigkeit

opel = Fahrzeug("Opel Admiral", 60)
volvo = Fahrzeug("Volvo Amazon", 45)

if opel > volvo :
        print("Opel ist schneller")
elif opel == volvo :
        print("Beide sind gleich schnell")
else :
        print("Volvo ist schneller")


differenz = opel - volvo
print("Geschwindigkeitsdifferenz:", differenz, "kmh/h") 
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@d_rose: Der Haken liegt bei der Einrückung. Du hast nur eine Methode definiert, nämlich die `__init__()`. Und in der dann drei Funktionen. Das sollten aber Methoden auf der Klasse sein und keine Funktionen innerhalb von `__init__()` die nicht verwendet werden.

Es ist auch zu weit eingerückt – Konvention sind vier Leerzeichen pro Ebene. Du hast da auch vor ein paar Doppelpunkten ein Leerzeichen.

Wenn man `__gt__()` implementiert, sollte man auch `__lt__()`, `__ge__()`, und `__le__()` implementieren und wenn man `__eq__()` implementiert, sollte man auch `__ne__()` und `__hash__() implementieren. `__lt__()`, `__ge__()`, `__le__()` und `__ne__()` braucht man nicht selbst zu schreiben wenn man den Dekorator `functools.total_ordering` auf die Klasse anwendet. Und für `__hash__()` kann man, wenn man sich da keine Gedanken machen möchte, einfach einen `TypeError` auslösen, wie `list` das zum Beispiel macht.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
sls
User
Beiträge: 480
Registriert: Mittwoch 13. Mai 2015, 23:52
Wohnort: Country country = new Zealand();

Das mit dem "Opel Admiral" kommt mir bekannt vor. Könnte ein Buch vom Theis sein. Würde sich mit der Code-Qualität decken.
When we say computer, we mean the electronic computer.
d_rose
User
Beiträge: 57
Registriert: Dienstag 30. Oktober 2018, 11:34

Nein, wie peinlich. Das mir sowas billiges nicht aufgefallen ist, ist traurig.
Dennoch vielen dank.
Buch ist vom Theis, gibt Sachen die ich erst durch sein Buch verstehe, gibt Sachen die ich durch andere Person erst verstehe.
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@d_rose: Noch Anmerkungen zum Code: Man sollte keine Abkürzungen benutzen. Also die kryptischen `bez` und `ge` bei `Fahrzeug.__init__()` genau so ausschreiben wie bei den Attributen auch.

Die Subtraktion auf diese Art zu überladen ist keine gute Idee. Das bricht mit den Erwartungen des Lesers. Erst einmal fragt man sich ja sowieso schon was das wohl bedeuten mag wenn man ein Auto von einem anderen abzieht. Das macht keinen Sinn. Und dann würde man bei so einer Operation auch wieder einen Ergebnistyp erwarten der sich weiterhin wie ein Fahrzeug verhält, denn wenn Subtraktion definiert ist, kann man ja auch so etwas schreiben:

Code: Alles auswählen

    print(opel)
    opel -= volvo
    print(opel)
Und hier wird dann aus einem `Fahrzeug` eine Zahl, was mehr als schräg ist.

Hier die überarbeitete Variante:

Code: Alles auswählen

#!/usr/bin/env python3
from functools import total_ordering


@total_ordering
class Fahrzeug:

    def __init__(self, bezeichnung, geschwindigkeit):
        self.bezeichnung = bezeichnung
        self.geschwindigkeit = geschwindigkeit

    def __repr__(self):
        return (
            f'{self.__class__.__name__}({self.bezeichnung!r},'
            f' {self.geschwindigkeit!r})'
        )

    def __hash__(self):
        raise TypeError(f'{type(self)} is unhashable')

    def __eq__(self, other):
        return self.geschwindigkeit == other.geschwindigkeit
    
    def __gt__(self, other):
        return self.geschwindigkeit > other.geschwindigkeit
    
    def __sub__(self, other):
        return self.geschwindigkeit - other.geschwindigkeit


def main():
    opel = Fahrzeug('Opel Admiral', 60)
    volvo = Fahrzeug('Volvo Amazon', 45)
    print(opel, volvo)

    if opel > volvo:
        print('Opel ist schneller')
    elif opel < volvo:
        print('Volvo ist schneller')
    else:
        print('Beide sind gleich schnell')

    differenz = opel - volvo
    print('Geschwindigkeitsdifferenz:', differenz, 'km/h')
    
    print(opel)
    opel -= volvo
    print(opel)


if __name__ == '__main__':
    main()
Den Vergleich in der Hauptfunktion habe ich etwas umgestellt und ``>`` und ``<`` verwendet, um zu zeigen das man durch den `total_ordering`-Dekorator jetzt auch die Vergleichoperatoren verwenden kann, die man nicht explizit implementiert hat.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Antworten