Verbesserungsvorschläge....

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.
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

Hallo zusammen,

ich mal wieder zur Abwechslung :D

Abgesehen davon, dass das Programm noch fertig geschrieben werden muss: was würdet ihr unbedingt anders machen und warum? Vielen Dank im Voraus!

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: cp1252 -*-

from math import pi, pow


def eingaben_check(*eingaben):
    try:
        return [int(eingabe) for eingabe in eingaben]
    except ValueError:
        print "Fehler bei der Eingabe!"
        return False
    

def umfang_rechteck(a, b):
    return (a + b) * 2

def flaeche_rechteck(a, b):
    return a * b

def umfang_dreieck(a, b, c):
    return a + b + c

def flaeche_rwdreieck(a, b):
    return (a * b) / 2

def umfang_kreis(r):
    return 2 * r * pi

def flaeche_kreis(r):
    return pow(r, 2) * pi


if __name__ == "__main__":
    
    print "============Menü============"
    print "1. Umfang Rechteck"
    print "2. Fläche Rechteck"
    print "3. Umfang Dreieck"
    print "4. Fläche Rechtw. Dreieck"
    print "5. Umfang Kreis"
    print "6. Fläche Kreis"
    print "e für Ende"
    print "============================="

    while True:
        
        auswahl = raw_input("Bitte treffen Sie eine Auswahl: ")
        if auswahl == "1":
            a = raw_input("Bitte einen Wert für a eingeben: ")
            b = raw_input("Bitte einen Wert für b eingeben: ")
            test = eingaben_check(a, b)
            if test:
                ergebnis = umfang_rechteck(*test)
                print "Die Fläche des Rechtecks beträgt", ergebnis
        elif auswahl == "2":
            pass
        elif auswahl == "e":
            break
        else:
            print auswahl, "ist eine ungültige Eingabe!"


    print "Ende des Programms"

LG

r_r
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

Code: Alles auswählen

from operator import mul as flaeche_rechteck
;)
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

Guter Tipp,....

allerdings gings mir persönlich, was wohl unklar war, mehr um die ganze Geschichte - Eingabe, Überprüfung, Verarbeitung, Ausgabe...

Dennoch werde ich mul wie vorgeschlagen berücksichtigen :D

LG

r_r
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

Von mir selbst....

Code: Alles auswählen


def eingaben_check(*eingaben):
    try:
        return [int(eingabe) for eingabe in eingaben]
    except ValueError:
        print "Fehler bei der Eingabe!"
        return False

Code: Alles auswählen

return False

ist eigentlich umsonst, oder?
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

Wenn du das "return False" weg lässt, wird eben im Fehlerfall None statt False zurück gegeben.
Bottle: Micro Web Framework + Development Blog
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

Ok, es ist spät....vielleicht deshalb....aber was ändert in dem Fall "None" gegenüber "False"?

Grüße, r_r
BlackJack

@rolgal_reloaded: `None` ist halt was anderes als `False`. Ausserdem fehlt ohne das explizite ``return`` in der Funktion ein IMHO wichtiger Hinweis für den Leser, nämlich was im Fehlerfall zurück gegeben wird. Das es ein implizites ``return None`` am Ende jeder Funktion gibt, ist ja ain ganz klein wenig "Magie", die man kennen muss.

Ich finde aber Fehlerrückgabewerte sowieso nicht so toll. Insbesondere wenn man eine Ausnahme in einen solchen "umwandelt". Ausnahmen sind ja gerade dazu erfunden worden, um solche "speziellen" Werte loswerden zu können.

Die Argumentüberhabe mit ``*`` vermeide ich so gut wie's geht. IMHO ist sie hier überflüssig, denn wenn sowohl in der Funktionssignatur als auch beim Aufruf der ``*`` nötig ist, kann man ihn auch an beiden Stellen weglassen.

Statt der "list comprehension" könnte man auch ``map(int, eingaben)`` schreiben.

`test`!? Der Name passt nicht.

Und wenn man keine ganzen Zahlen eingibt, dann bekommt man keine Fehlermeldung!?

Wenn Du die anderen Zweige mit Quelltext füllst, wirst Du wahrscheinlich feststellen, dass die am Ende sehr ähnlichen Quelltext enthalten. Da sollte man dann überlegen etwas generischeres zu schreiben, was dann entsprechend parametrisiert wird.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Wenn du im Fehlerfall False zurückgibst, dann solltest du bei Erfolg auch True zurückgeben. None ist gerade für solche Fälle wie deinen geeignet: Entweder man hat ein Ergebnis (deine Liste) oder keins (None).

Deine LC kanst du übrigens aucheinfach so schreiben:

Code: Alles auswählen

return map(int, eingaben)
Ich würde aber die Ausgabe lieber direkt Abfangen als über einen Rückgabewert.

Sebastian
Das Leben ist wie ein Tennisball.
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

BlackJack hat geschrieben:@rolgal_reloaded:

Die Argumentüberhabe mit ``*`` vermeide ich so gut wie's geht. IMHO ist sie hier überflüssig, denn wenn sowohl in der Funktionssignatur als auch beim Aufruf der ``*`` nötig ist, kann man ihn auch an beiden Stellen weglassen.
Hätte ich auch gemeint, funzt aber nicht. Aber wahrscheinlich übersehe ich etwas weiteres ?!
Statt der "list comprehension" könnte man auch ``map(int, eingaben)`` schreiben.
Ist schön, hat aber für Anfänger auch wieder was von Magie.
`test`!? Der Name passt nicht.
Gibt wahrscheinlich noch besseres, aber warum passt es nicht?
Und wenn man keine ganzen Zahlen eingibt, dann bekommt man keine Fehlermeldung!?
Machen wir float, nehme an, du hast das gemeint.
Wenn Du die anderen Zweige mit Quelltext füllst, wirst Du wahrscheinlich feststellen, dass die am Ende sehr ähnlichen Quelltext enthalten. Da sollte man dann überlegen etwas generischeres zu schreiben, was dann entsprechend parametrisiert wird.
Das steht außer Zweifel, aber du weisst eh...

LG

r_r
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

EyDu hat geschrieben:Wenn du im Fehlerfall False zurückgibst, dann solltest du bei Erfolg auch True zurückgeben. None ist gerade für solche Fälle wie deinen geeignet: Entweder man hat ein Ergebnis (deine Liste) oder keins (None).
Auch ein Aspekt, vor allem durchaus auch erklärbar.

Ich würde aber die Ausgabe lieber direkt Abfangen als über einen Rückgabewert.

Sebastian
Vorschlag in Bezug auf das Beispiel?

LG

r_r
BlackJack

@rolgal_reloaded: `map()` ist eine ganz normale Funktion, da sehe ich nichts magisches.

`test` enthält keinen Test und auch kein Ergebnis eines Tests, darum passt der Name halt nicht. Halt nein: *manchmal* wird der Name doch an so etwas wie ein Testergebnis gebunden. Aber dass ich das nicht so vorteilhaft finde, habe ich ja schon geschrieben.

Nein `float()` meine ich nicht. Ich dachte der Benutzer wird nicht über Falscheingaben informiert. Da habe ich übersehen, dass die Umwandlungsfunktion nicht nur testet, sondern auch eine Ausgabe macht. Das gehört da IMHO auch nicht rein. Man sollte Logik und Benutzerinteraktion trennen.
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

BlackJack hat geschrieben:@rolgal_reloaded: `map()` ist eine ganz normale Funktion, da sehe ich nichts magisches.
Na ich auch nicht :D
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

Wenn ich über Eure Anregungen nachdenke, komme ich zu folgender Fassung, ist wohl besser?

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: cp1252 -*-

from math import pi, pow

  

def umfang_rechteck(a, b):
        return (a + b) * 2

def flaeche_rechteck(a, b):
    return a * b

def umfang_dreieck(a, b, c):
    return a + b + c

def flaeche_rwdreieck(a, b):
    return (a * b) / 2

def umfang_kreis(r):
    return 2 * r * pi

def flaeche_kreis(r):
    return pow(r, 2) * pi


def ausgabe(funktion, *eingaben):
    try:
        ergebnis = funktion(*map(float, eingaben))
        print "Das Ergebnis lautet: ", ergebnis
        
    except ValueError:
        print "Fehler bei der Eingabe!"
        

if __name__ == "__main__":
    
    print "============Menü============"
    print "1. Umfang Rechteck"
    print "2. Fläche Rechteck"
    print "3. Umfang Dreieck"
    print "4. Fläche Rechtw. Dreieck"
    print "5. Umfang Kreis"
    print "6. Fläche Kreis"
    print "e für Ende"
    print "============================="

    while True:
        
        auswahl = raw_input("Bitte treffen Sie eine Auswahl: ")
        if auswahl == "1":
            a = raw_input("Bitte einen Wert für a eingeben: ")
            b = raw_input("Bitte einen Wert für b eingeben: ")
            
            ausgabe(umfang_rechteck, a, b)
                
        elif auswahl == "2":
            pass
        elif auswahl == "e":
            break
        else:
            print auswahl, "ist eine ungültige Eingabe!"


    print "Ende des Programms"
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

Du solltest dir noch eine main-Funktion anlegen.

Noch ein Tipp für die Benutzereingaben:

Code: Alles auswählen

>>> spam = {1:lambda x: x*2, 2:lambda x: x*x}
>>> spam[1](4)
8
>>> spam[2](4)
16
>>>
Die Abfragen von a, b und r kannst du dort auch noch einbauen. Aber nicht in die Berechnungsfunktionen und ohne zusätzliche Funktion für jede Berechnung.
Das Leben ist wie ein Tennisball.
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

EyDu: Du empfiehlst aufsteigende ganze Zahlen als Schlüssel für dicts zu verwenden? Warum?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

derdon hat geschrieben:EyDu: Du empfiehlst aufsteigende ganze Zahlen als Schlüssel für dicts zu verwenden? Warum?
Das hat etwas mit der Erdrotation zu tun, ist aber viel komplex um das hier zu erläutern.
Das Leben ist wie ein Tennisball.
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

Code: Alles auswählen

def umfang_rechteck(a,b):
    return a*b

def end():
    raise KeyboardInterrupt

def main():
    options = {'1': dict(str='Umfang Rechteck', func=umfang_rechteck, params=('a','b')),
                'e': {'func': end},
                }
    
    def print_menu():
        print 'Menu'
        for i in range(1, len(options)):
            print '%s. %s' %(i, options[str(i)]['str'])
        print 'e for end'
        print
    
    def get_choice():
        exercise = None
        while not exercise:
            choice = raw_input('Bitte treffen Sie eine Auswahl: ')
            exercise = options.get(choice, None)
        params = {}
        for param in exercise.get('params', ()):
            params[param] = int(raw_input("Bitte einen Wert fuer %s eingeben: " %param))
        return exercise['func'], params
    
    try:
        while True:
            print_menu()
            func, kwargs = get_choice()
            print func(**kwargs)
            print
    except KeyboardInterrupt:
        print 'end'

if __name__ == '__main__':
    main()
Ganz so schön ist das nicht gemacht mit dem Mischen von Zahlen und dem "e".
[url=http://wiki.python-forum.de/PEP%208%20%28%C3%9Cbersetzung%29]PEP 8[/url] - Quak!
[url=http://tutorial.pocoo.org/index.html]Tutorial in Deutsch[/url]
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

Warum eine Funktion main?

Das wirkt für mich überflüssig :?:

Und ob die Funktionen im Dict. besser lesbar sind....da kann ich sie doch frisch ausschreiben, der Zweizeiler ist mir da sympahtischer, oder gibts in deiner Fassung einen wesentlichen Vorteil?

LG

r_r
BlackJack

@rolgal_reloaded: `main()` weil Code und Variablen auf Modulebene unsauber sind. Da besteht halt immer die Gefahr, dass man die aus versehen oder absichtlich zur Kommunikation zwischen Funktionen oder Methoden verwendet und damit unnötige Abhängigkeiten einbaut die schwerer zu verstehen sind.

Von welchen zwei Zeilen Code redest Du? Überleg Dir mal wie man bei Deinem Code weitere Funktionen hinzufügt und wie das bei jbs' Code aussieht.
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

BlackJack hat geschrieben:@rolgal_reloaded: `main()` weil Code und Variablen auf Modulebene unsauber sind. Da besteht halt immer die Gefahr, dass man die aus versehen oder absichtlich zur Kommunikation zwischen Funktionen oder Methoden verwendet und damit unnötige Abhängigkeiten einbaut die schwerer zu verstehen sind.

Von welchen zwei Zeilen Code redest Du? Überleg Dir mal wie man bei Deinem Code weitere Funktionen hinzufügt und wie das bei jbs' Code aussieht.
Ich rede von den zwei Zeilen, die meine Funktionen für die Berechnungen haben.

LG r_r
Antworten