Frage an die "Python-Experten hier im Forum"

  • Ich bin dabei, mich ein wenig in Python einzuarbeiten.


    Ich habe dazu einen entsprechenden Programmcode geschrieben, um eine Berechnung eines "Rechtwinkligen" Dreiecks zu erstellen.


    Der Ablauf ist folgender:

    Für eine Berechnung müssen 2 Werte bekannt sein. Entweder zwei Katheten oder eine Kathete und der Winkel alpha (Spitzenwinkel)


    Bei Programmstart werden zunächst 2 Katheten abgefragt. Unbekannte werden mit "0" eingegeben.

    Sind die ersten beiden nicht 0, wird sofort die Berechnung durchgeführt und die anderen beiden Werte werden als Ergebnis ausgegeben.

    Ist einer der ersten beiden Werte unbekannt, wird eine dritte Kathete abgefragt. Sind wieder zwei bekannte vorhanden, wird wieder berechnet und das Ergebnis ausgegeben.

    Falls nicht, wird der Winkel auch noch abgefragt.


    Den Code habe ich komplett selber geschreiben. (Kein Copy/Paste)


    Das Programm läuft einwandfrei.


    Meine Frage ist, ob der Code so "ok" ist, oder ob ich da noch etwas verändern sollte. ( Vorschläge hinsichtlich Verbesserungen nehme ich gerne an.)




  • Franjo G: Mal hinten anfangend: Das `input()` am Ende ist sinnlos bis nervig. So etwas machen Konsolenprogramme nicht.


    Das Programm reagiert IMHO nicht so toll wenn man ungültige Werte eingibt, wie negative Werte oder nur 0en.


    Bei der Abfrage von `angle_alpha` steht drei mal fast der gleiche Code. Das kann man alles in eine Bedingung packen und die auch eher so formulieren wie der Kommentar das beschreibt: Zählen wie viele unbekannte Seiten es gibt.


    Bei den Berechnungen und um `str()`-Aufrufe sind teilweise sinnlose Klammern. Die sind unnötig und tragen auch nicht zum besseren Verständnis bei.


    Namen durchnummerieren ist keine gute Idee. Man weiss beim Lesen der Namen `output1()` und `output2()` nicht was diese Funktionen machen. Und die werden auch immer beide direkt nacheinander aufgerufen, das könnte man also auch in *eine* Funktion stecken. Oder einfach ”inline” schreiben. Das erste `print()` kann man auch nur *einmal* in das Hauptprogramm nach der letzten Benutzereingabe schreiben.


    Von den ganzen ``if``\s bei den Berechnungen + Ausgaben sollte ja nur *eine* Bedingung zutreffen, das heisst man würde hier besser mit ``elif`` arbeiten, damit nicht unnötig die ganzen Bedingungen nach dem Treffer auch noch geprüft werden. Und man kann in einem abschliessenden ``else`` dann auch eine Fehlermeldung ausgeben.


    Man muss nicht jedes Zwischenergebnis an einen (schlechten) Namen binden.


    Ungetestet:

    Who is General Failure and why is he reading my hard disk?

  • erst mal danke für's drüberschauen.


    Dass das Programm nicht perfekt ist war mir klar. Aber dafür, dass ich vor 3 -4 Tagen die erste Python-Zeile geschrieben habe, bin ich schon froh, dass es läuft. :)

    Das `input()` am Ende ist sinnlos bis nervig.

    Da ich das mit Windows nutze, habe ich das so reingeschrienem, da das Fenster nach der letzten Eingabe sofort geschlossen wird.


    Bei den Berechnungen und um `str()`-Aufrufe sind teilweise sinnlose Klammern.

    Bei den sin, cos.... Berechnungen habe ich mit der Syntax schwer getan. Da habe ich so lange rumgebastelt, bis die richtigen Ergebnisse und keine Fehlermeldungen rauskamen. War nicht ganz so einfach mit math.degrees, math.tan..


    Namen durchnummerieren ist keine gute Idee.

    Da gebe ich dir vollkommen recht. Aber bei den paar Zeilen und den zwei Namen habe ich mich dennoch dazu hinreißen lassen :(

  • Hallo,


    zur weiteren Übung könntest du die Eingabe des Winkels noch überprüfen. Würde man z.B. für 'angle_alpha' 242 eingeben, würde die WInkelfunktion zwar etwas berechnen, das hätte aber mit einem rechtwinkligen Dreieck nichts zu tun.

    Vielleicht kannst du auch zur Prüfung die Winkelsumme berechnen.

    Das mit den Argumenten übergeben funktioniert ja schon, du könntest ja mal zum Beispiel die Prüfung der Eingaben in einer eigenen Funktion durchführen und dann, je nach dem was die Prüfung ergab, die Funktion wieder einen Wert zurückgeben lassen und dann die Berechnung starten.

    Ihr habt beide ein 'print()' in Programm, zu was, wenn nichts ausgegeben wird?



    Grüße

    Dennis

    ... ob's hinterm Horizont wirklich so weit runter geht oder ob die Welt vielleicht doch gar keine Scheibe ist?

  • Ihr habt beide ein 'print()' in Programm, zu was, wenn nichts ausgegeben wird?

    Das print() oben habe ich eingesetzt, um zwischen Ein-und Ausgabetext eine Leerzeile einzufügen.

    Das ganz unten ist überflüssig


    Was bewirkt die def main() Funktion?

  • Um Absätze einzufügen kannst du '\n' einfügen, also zum Beispiel print("Erster Text\nneue Zeile")


    In Python wird die Funktion, die das Programm steuert üblicherweise 'main' genannt. Es ist nicht gewünscht das ausführbarer Code auf oberster Ebene steht. Also an der Stelle ohne Einrückungen, wo fast dein kompletter Code steht. Ohne Einrückungen steht nur Code der Konstanten, Klassen oder Funktionen beschreibt und am Ende des Programms die typische 'if __name__ == '__main__':' -Abfrage. Die ist notwendig und wichtig. Sie sorgt dafür dass die 'main'-Funktion ausgeführt wird, wenn das Programm direkt gestartet wird und sie sorgt dafür, dass das Programm *nicht* von selbst ausgeführt wird, wenn man es beispielsweise in ein anderes importiert. Im Gegensatz dazu würde jeder Code der auf Modulebene steht ausgeführt, wenn man das Programm in ein anderes importiert.

    Siehe dazu hier


    Die 'main'-Funktion steuert dein Programm. Daraus werden Funktionen aufgerufen, Argumente übergeben und es werden Rückgaben von Funktionen wieder entgegen genommen.


    Grüße

    Dennis

    ... ob's hinterm Horizont wirklich so weit runter geht oder ob die Welt vielleicht doch gar keine Scheibe ist?

  • könntest du die Eingabe des Winkels noch überprüfen.

    Ich habe jetzt mal eine while-schleife eingefügt. Das funktioniert zwar, aber da gibt es sicherlich eine bessere Lösung.

    So muss ich die input-Zeile angle_alpha = float(input ("Winkel_alpha         "))( zwei mal eingeben.


    Ich hatte versucht, sie oben in eine Funktion zu setzen und unten nur die funktion aufzurufen, aber das funktioniert nicht.

    angle_alpha wird zwar abgefragt, aber dann kommt die Meldung " zu viele Unbekannte "


  • Du könntest vor der Eingabe eine Schleife starten.

    Danach eine 'if'-Abfrage, je nach dem ob die erfüllt ist, wird die Schleife abgebrochen oder nicht.


    Code
        if sum(value == 0 for value in [side_a, side_b, side_c]) >= 2:
            while True:
                angle_alpha = float(input("Winkel_alpha      "))
                if not 45 > angle_alpha > 0:
                    break
                else:
                    print("Der Wertebereich für den Winkel ist nur von 0 bis 45 Grad")


    Grüße

    Dennis


    Edit: Franjo G Nur um nicht einen falschen Eindruck zu erwecken, falls jemand so ein Programm suchst, wie du gerade schreibst. Der Winkel darf an sich schon größer wie 45° sein. Die Winkelsumme darf im rechtwinkligen Dreieck nur 180° nicht überschreiten. 90° sind schon vorgegeben und die übrigen 90° können dann aufgeteilt werden. Also 60/30 würde auch gehen.

    ... ob's hinterm Horizont wirklich so weit runter geht oder ob die Welt vielleicht doch gar keine Scheibe ist?

    Edited once, last by Dennis89 ().

  • Noch eine kleine Erweiterung, wenn du so Helden wie mich hast, die tippen hier doch dann glatt Buchstaben ein und das Skript stürzt ab =O

    Python
    Traceback (most recent call last):
      File "C:/Users/***/PycharmProjects/test/eingabe.py", line 2, in <module>
        angle_alpha = float(input("Winkel_alpha      "))
    ValueError: could not convert string to float: 'l'

    Außerdem stimmt hier die Logik nicht

    Code
    if not 45 > angle_alpha > 0:


    Meine Ergänzung:

    Python
    while True:
        try:
            angle_alpha = float(input("Winkel_alpha      "))
        except ValueError:
            print("Nur Zahlen zwischen 0 - 45 eingeben!")
        else:
            if 0 < angle_alpha <= 45:
                break
            else:
                print("Der Wertebereich für den Winkel ist nur von 0 bis 45 Grad")

    und hier noch etwas gekürzt:

    Python
    while True:
        try:
            angle_alpha = float(input("Winkel_alpha      "))
            if not 0 < angle_alpha <= 45:
                raise ValueError
        except ValueError:
            print("Nur Zahlen zwischen 0 - 45 eingeben!")
        else:
            break
  • while True:

    angle_alpha = float(input("Winkel_alpha "))

    if not 45 > angle_alpha > 0:

    break

    else:

    So wird nur der Wert 45 begrenzt. if not 45 < angle_alpha > 0

    So wird nur der Wert 0 begrenzt if not 45 > angle_alpha < 0


    Keine Funktion in deinem Beispiel if not 45 > angle_alpha >0


    Alle anderen Variationen bewirken gar nichts. Getestet mit dem Wert 1 und einer Eingabe von 0.9


    Die Eingabe von 0 wird eh schon mit einem Fehler (zu viele Unbekannte) ausgegeben.


    Daher habe ich das jetzt so geändert.

    Code
        if sum(value == 0 for value in [side_a, side_b, side_c]) >= 2:
            while True:
                angle_alpha = float(input("Winkel_alpha      "))
                if not 45 < angle_alpha:
                    break
                else:
                    print("\nDer Wertebereich für den Winkel ist nur von 0 bis 45 Grad\n")
    Code
    Gegenkathete_A    0
    Ankathete_B       0
    Hypothenuse_C     10
    Winkel_alpha      46
    
    Der Wertebereich für den Winkel ist nur von 0 bis 45 Grad
    
    Winkel_alpha      
  • Franjo G Das reicht aber nicht nur gegen 45 zu testen, denn jetzt kann jemand negative Winkel eingeben. (Und besondere Scherzkekse (wie ich 🤡) geben auch gerne mal "inf", "-inf", und "nan" ein, um zu sehen was passiert.)

    Who is General Failure and why is he reading my hard disk?

  • Außerdem stimmt hier die Logik nicht
    Code if not 45 > angle_alpha > 0:


    if not 0 < angle_alpha <= 45:


    Auch das funktioniert nicht. Gleiches Problem wie bei Dennis89

  • denn jetzt kann jemand negative Winkel eingeben.

    Nein, negative Werte gehen nicht, weil alle Abfragen > 0 lauten. Egal, wo ich einen negativen Wert eingebe, kommt immer die Antwort "zu viele Unbekannte"


  • Hofei


    Dein Beispiel aus #10 funktioniert doch. Ich hatte zunächst nur die eine Zeile if not 0 < angle_alpha <= 45 geändert. Da funktionierte es nicht.

    Erst als ich dein komplettes Beispiel übernommen hatte, ging es.

    Das funktioniert auch mit 0

  • Der Winkel darf an sich schon größer wie 45°

    Es geht um den Winkel alpha. Das ist der spitzeste Winkel gegenüber von Seite a (Gegenkathete)

    Wenn der Winkel mehr als 45 Grad hat, wird er zum Winkel beta und die Gegenkathete wird zur Ankathete,

    Bei 45 Grad sind die Ankathete und die Gegenkathete gleich lang und die Winkel alpha und beta beide 45 Grad.


  • Mir sind die Winkelfunktionen bekannt und den Funktionen ist es egal ob du den Winkel alpha, beta oder „grüner Elefant“ nennst.

    Die Ankathete ist immer die Seite die der Winkel einschließt. Und die Gegenkathete ist immer gegenüberliegend.

    Wir einer größer wird der andere kleiner und das funktioniert im rechtwinkligen Dreieck solange, bis die Summe aus allen drei Winkeln 180 Grad überschreitet.


    Kann dir nachher dazu gerne noch Skizzen und Rechnungen machen, ist am Handy nur ungeschickt gerade.


    Sorry das ich das „not“ in Raum geworfen habe und damit für Probleme im Programm gesorgt habe. :blush:


    Grüße

    Dennis

    ... ob's hinterm Horizont wirklich so weit runter geht oder ob die Welt vielleicht doch gar keine Scheibe ist?

  • und den Funktionen ist es egal ob du den Winkel alpha, beta oder „grüner Elefant“ nennst.

    rein rechnerisch hast du Recht. Du kannst auch mit einem Winkel von über 90 Grad rechnen.

    Was halt nicht geht, sind genau 90, 180,270,360..... Das wären keine Dreiecke, sondern Geraden. Das gibt einen mathematischen Fehler.


    Wenn du z.B. 45 Grad eingibst, erhälst du die gleichen Werte wie bei 225 Grad. Halt nur mit negativen Vorzeichen.

    405 Grad ist wiederum das gleiche wie 45 Grad.


    Somit brauchst du den Winkel im Grunde gar nicht begrenzen. Du musst nur in der Fertigung etwas aufpassen.


  • Wenn du z.B. 45 Grad eingibst, erhälst du die gleichen Werte wie bei 225 Grad. Halt nur mit negativen Vorzeichen.

    Das lässt sich an Hand des Einheitskreises (Seite ganz unten) grafisch schön darstellen. Auf der Seite kann man mit einem Schieber den Winkel verändern und sieht dann dabei den Zusammenhand der Winkel und den Vorzeichen.



    Du musst nur in der Fertigung etwas aufpassen.

    Um jetzt nicht so weit von deinem Python-Thema abzuweichen. Ist das nur zu Übungszwecken oder willst du etwas bestimmtes fertigen, wo dir das Programm weiter hilft?


    Grüße

    Dennis

    ... ob's hinterm Horizont wirklich so weit runter geht oder ob die Welt vielleicht doch gar keine Scheibe ist?

  • Anbei ein paar Kommentare von meiner Seite:


    1) Mit der schon angesprochenen Eingabepruefung ist das immer eine Sache die man nicht gerne vergisst und auch aufwaendig ist. Solange man das Programm selbst nutzt kann man sie weglassen. In aller anderen Faellen sollte man gut pruefen.


    2) Einen bestimmten Wert aus der Eingabemenge zu nehmen und ihn dazu zu nutzen zu signalisieren dass der Wert nicht eingegeben wurde ist einfach implementiert. Ich wuerde aber trotzdem boolsche Variablen nutzen um dieses zu signalisieren. Bei groesseren Projekten zeigt sich immer wieder dass sowas zu Fehlern bei Wartung oder Erweiterung eines Programms fuehrt. Wenn es denn unbedingt sein muss wuerde ich eine kleine Funktion definieren wie z.B. istDefiniert(x) = x == 0 und diese immer nutzen und nicht auf Null abfragen. Wer immer den Code liest versteht braucht nicht zu wissen dass 0 eigentlich dazu missbraucht wird um "Wert nicht definiert" zu signalisieren.


    3) Ich wuerde das UserInterface etwas anders definieren: Man fragt nicht erst einmal 2 Variablen ab die u.U. nicht notwendig sind (Variable == 0) sondern gibt nur ein welche Variablen bekannt sind und die unbekannten Variablen werden dann berechnet. Also z.B. gibt es nur eine EIngabe der Form AK=5 GK=7 oder alpha=34 AK=10. Das erfordert dann zwar keinen richtigen Syntaxparser aber etwas muss die Eingabe dann schon geparsed werden um die definierten Variablen zu identifizieren und mit entsprechenden Werten vorzubesetzen. Vielleicht nimmst Du Dir dieses fuer eine Veriosn 2 Deines Programmes vor ;)

    "Really, I'm not out to destroy Microsoft. That will just be a completely unintentional side effect." Linus Benedict Torvalds, 28.9.2003


    Hast Du die Woche schon Deine Raspberry gesichert :shy: Bei mir tut das automatisch raspiBackup ;)