zurückspringen bzw auswahl wiederholen?

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.
nevergod
User
Beiträge: 46
Registriert: Mittwoch 22. September 2010, 13:22

Guten tag,
Ich habe gerade angefangen python zu lernen und habe bereits ein kleines Programm geschrieben.
Das geht so nach dem motto

Liste wird angezeigt -> etwas aus der liste wählen -> wenn es was aus der liste war x ausführen
-> wenn nicht print anzeigen und zurück zum anfang

Das zurück zum anfang klappt bei mir nicht so :K um ehrlich zu sein weiß ich nichtmal wirklich wie ich das anstellen soll.

Hoffe mir kann da jemand helfen :)

mfG. NeverGod
Benutzeravatar
lutz.horn
User
Beiträge: 205
Registriert: Dienstag 8. November 2005, 12:57
Wohnort: Pforzheim

Poste doch Deinen Code, dann können wir Dir helfen.
https://www.xing.com/go/invite/18513630.6a91d4
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Schau dir mal while-Schleifen an.
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
nevergod
User
Beiträge: 46
Registriert: Mittwoch 22. September 2010, 13:22

Code: Alles auswählen

# -*- coding: utf-8 -*-
import msvcrt
import time
import math

print "Wilkommen zum Programm fuer die Flaechen/Volumenberechnung"
print "von Formen und Koerpern."
print " "
print "Bitte waehlen sie aus der folgenden Liste welche Berechnung sie"
print "durchfuehren moechten"
print " "
print "Benutzerhinweis : Anstatt die ueblichen Kommata (,) benutzen sie"
print "bitte Punkte (.) !"

print " 1 = Flaechenberechnung eines Vierecks "
print " 2 = Volumenberechnung eines Quaders "
print " 3 = Flaechenberechnung eines Kreises "
print " 4 = Flaechenberechnung eines Dreiecks "


Z = input("Bitte waehlen sie jetzt: ")
          
if Z == 1:
    print " Sie haben sich fuer die Berechnung eines Vierecks entschieden."
    a = input("Bitte geben sie hier die Laenge der ersten Seite ein: ")
    b = input("Bitte geben sie hier die Laenge der zweiten Seite ein: ")
    A = a * b
    print "Der Flaecheninhalt betraegt: ",A
    raw_input(" ")


elif Z == 2:
    print " Sie haben sich fuer die Berechnung eines Quaders entschieden."
    a = input("Bitte geben sie die Laenge des Quaders ein: ")
    b = input("Bitte geben sie die Breite des Quaders ein: ")
    c = input("Bitte geben sie die Hoehe des Quaders ein: ")
    A = a * b * c
    print "Das Volumen des Quaders betraegt: ",A
    raw_input(" ")

elif Z == 3:
    print " Sie haben sich fuer die Berechnung eines Kreises entschieden."
    a = float(input("Bitte geben sie den Radius des Kreises an: "))
    B = ( a * a ) * 3.141592653589793238462643383279
    print("Der Flaecheninhalt des Kreises betraegt: "),B
    raw_input(" ")

elif Z == 4:
     print "Sie haben sich fuer die Berechnung eines Dreiecks entschieden."
     a = input("Bitte geben sie die Laenge der Grundseite des Dreiecks an: ")
     b = input("Bitte geben sie die Hoehe des Dreiecks an: ")
     A = 0,5 * a * b
     print("Der Flaecheninhalt des Dreiecks betraegt: "),A
     raw_input(" ")

elif Z < 1:
    print "Bitte waehlen sie nur aus der liste"
    raw_input(" ")

elif Z > 4:
    print "Bitte waehlen sie nur aus der liste"
    raw_input(" ")
das ist der code ^^ wie gesagt bei elif Z<1 und 5 würd ich gerne machen das er wieder zurück an anfang springt (nach dem print) und wieder die liste anzeigt
Benutzeravatar
lutz.horn
User
Beiträge: 205
Registriert: Dienstag 8. November 2005, 12:57
Wohnort: Pforzheim

Pack alles in ein 'while True:' und bau einen Fall für ein Break ein.
https://www.xing.com/go/invite/18513630.6a91d4
BlackJack

@nevergod: Wie Rebecca schon sagte: ``while``-Schleife. "Springen" in Form einer GOTO-Anweisung gibt's in strukturierten Programmiersprachen in der Regel nicht.

Noch ein paar Anmerkungen:

`input()` solltest Du nicht benutzen, da wird ein Python-Ausdruck vom Benutzer erwartet und ausgewertet. Da kann der Benutzer zum einen Sachen eingeben die "böse" Sachen machen, und zum anderen ist es für Dich als Programmierer schwierig auf Fehleingaben zu reagieren. Da kann nämlich so ziemlich alles passieren, inklusive `SyntaxError` wenn der Benutzer etwas eingibt was kein korrekter Python-Ausdruck ist. Das trifft zum Beispiel sogar schon auf die leere Eingabe zu, also wenn der Benutzer einfach nur die Eingabetaste drückt. Also besser `raw_input()` und die Zeichenkette in den gewünschten Typ umwandeln.

Code sollte möglichst nicht auf Modulebene stehen und man sollte längere Quelltexte auf verschiedene Funktionen aufteilen.

Wenn etwas am Ende von *jedem* Zweig bei ``if``/``elif``/``else`` gemacht wird, dann kann man das auch *einmal* und *danach* machen.

Die Konstante für Pi ist im `math`-Modul bereits definiert.

Die Berechnung vom Dreieck hast Du offensichtlich nicht ausprobiert, denn da kommt eine "komische" Ausgabe bei heraus. :-)

Die Bedingungen der beiden letzten ``elif``\s lassen sich zusammenfassen bzw. willst Du das ja haben wenn keine der anderen Bedingungen zugetroffen hat -- also eigentlich ist das ein bedingungsloser ``else``-Zweig.

Weder `msvcrt` noch `time` werden verwendet.
nevergod
User
Beiträge: 46
Registriert: Mittwoch 22. September 2010, 13:22

Okay vielen dank ^^

die imports sind eigentlich nur alle drinn weil ich halt was rumprobiert habe und vergessen habe die rauszumachen.

werde die tipps beherzigen :D wie gesagt fange ja gerade erst an zu lernen :)
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

Schau auf jeden Fall mal ins Tutorial rein. :)
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Hallo nevergod,

ich bin auch noch ziemlich am Anfang, deshalb wird es an meinem Code sicherlich auch noch einiges zum Bemängeln geben.

Aber was ich bisher gelernt habe, hab' ich mal versucht, umzusetzen:

Code: Alles auswählen

# -*- coding: utf-8 -*-

import os
import math

AUSWAHL_TXT = (('Flächen', 'Vierecks'), \
    ('Volumen', 'Quaders'), \
    ('Flächen', 'Kreises'), \
    ('Flächen', 'Dreiecks'))
STATUS_TXT = ('Ihre Auswahl: ', \
    'OOPS! Falsche Eingabe! Bitte wählen Sie zwischen 1 und 4: ')
STATUS = 0

def menue():
    #Wenn Du Windows verwendest, muss hier statt 'clear' -> 'cls' stehen
    os.system('clear')
    print("Wilkommen zum Programm fuer die Flaechen/Volumenberechnung")
    print("von Formen und Koerpern.\n")
    print("Bitte waehlen sie aus der folgenden Liste welche Berechnung")
    print("sie durchfuehren moechten\n")
    print("Benutzerhinweis : Anstatt die ueblichen Kommata (,) benutzen")
    print("sie bitte Punkte (.) !\n\n")
    print("1 = Flaechenberechnung eines Vierecks ")
    print("2 = Volumenberechnung eines Quaders ")
    print("3 = Flaechenberechnung eines Kreises ")
    print("4 = Flaechenberechnung eines Dreiecks\n")
    print("0 = Ende\n")

def status(status):
    return(STATUS_TXT[status])

def bestaetigung(auswahl):
    print("\nSie haben sich für die %sberechnung eines %s entschieden." % \
        (AUSWAHL_TXT[auswahl-1][0], AUSWAHL_TXT[auswahl-1][1]))

def viereck():
    laenge_1 = float(raw_input('Erste Seite:  '))
    laenge_2 = float(raw_input('Zweite Seite: '))
    print('Der Flächeninhalt beträgt: %f' % \
        (laenge_1 * laenge_2))
    raw_input()

def quader():
    laenge = float(raw_input('Länge:  '))
    breite = float(raw_input('Breite: '))
    hoehe = float(raw_input('Höhe:   '))
    print('Das Volumen des Quaders beträgt: %f' % \
        (laenge * breite * hoehe))
    raw_input()

def kreis():
    radius = float(raw_input('Radius: '))
    print('Der Flächeninhalt des Kreises beträgt: %f ' % \
        ((radius * radius) * math.pi))
    raw_input()

def dreieck():
    laenge = float(raw_input('Länge: '))
    hoehe = float(raw_input('Höhe:  '))
    print('Der Flächeninhalt des Dreiecks beträgt: %f' % \
        (0.5 * laenge * hoehe))
    raw_input()

while True:
    menue()
    auswahl = int(raw_input(status(STATUS)))
    STATUS = 0
    if auswahl == 1:
        bestaetigung(auswahl)
        viereck()
    elif auswahl == 2:
        bestaetigung(auswahl)
        quader()
    elif auswahl == 3:
        bestaetigung(auswahl)
        kreis()
    elif auswahl == 4:
        bestaetigung(auswahl)
        dreieck()
    elif auswahl == 0:
        print('\nOver and out.')
        exit()
    else:
        STATUS = 1
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@mutetella: Die \ an den Zeilenenden sind alle überflüssig. Solange nich geöffnete Klammern nicht geschlossen wurden, weiss der Compiler auch so, dass die "logische Zeile" noch nicht zuende ist.

Namen komplett in Grossbuchstaben stehen per Konvention für Konstanten, `STATUS` wird aber während des Programms verändert.

Die Klammern bei den ``print``-Anweisungen sind irreführend. Das ist in Python <3 keine Funktion. Und Python 3.x kann es nicht sein, weil es dort den Namen `raw_input()` nicht mehr gibt. ``return`` ist ebenfalls keine Funktion.

Statt des Kommentars in `menu()` könnte man an der Stelle prüfen ob das Programm auf Windows läuft und dort entsprechend ``cls`` aufrufen. Bei Konsolenanwendungen die nicht tatsächlich eine "full screen" Oberfläche haben, ist das Löschen des Inhalts aber unüblich und auch nicht nett. Was immer da stand, könnte für den Benutzer wichtig gewesen sein, und nun kommt er da nicht mehr heran. Normalerweise kann man in den üblichen Konsolen-/Terminal-Fenstern ja nach oben scrollen um alte Ausgaben zu lesen, aber wenn man den Inhalt löscht ist zumindest eine "Seite" verloren.

Die `status()`-Funktion erscheint mir überflüssig.

Am Ende jeder Berechnungsfunktion steht ein ``raw_input()``, diese Wiederholung könnte man sich sparen. ``bestaetigung(auswahl)`` steht IMHO auch unnötig oft im Quelltext und die ``if``/``elif``-Kaskade könnte man durch ein Dictionary oder in diesem Fall auch eine Liste ersetzen. Ungetestet:

Code: Alles auswählen

def main():
    berechnungen = [viereck, quarder, kreis, dreieck]
    status = 0
    while True:
        menue()
        auswahl = int(raw_input(STATUS_TXT[status]))
        if auswahl == 0:
            print '\nOver and out.'
            break
        if 0 < auswahl < len(berechnungen):
            bestaetigung(auswahl)
            berechnungen[auswahl]()
            raw_input()
            status = 0
        else:
            status = 1
Du hast mit `AUSWAHL_TXT` ja schon so ein bisschen angefangen Gemeinsamkeiten der Berechnungen als Datenstruktur heraus zu ziehen -- das kann man noch viel weiter treiben, so dass man für eine weitere Berechnungsart das Programm nur noch an *einer* Stelle um einen entsprechenden Datensatz erweitern muss und nicht Änderungen über den gesamten Quelltext verstreut durchführen muss.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

BlackJack hat geschrieben:Die \ an den Zeilenenden sind alle überflüssig. Solange nich geöffnete Klammern nicht geschlossen wurden, weiss der Compiler auch so, dass die "logische Zeile" noch nicht zuende ist.
Peinlich... :oops:
BlackJack hat geschrieben:Namen komplett in Grossbuchstaben stehen per Konvention für Konstanten, `STATUS` wird aber während des Programms verändert.
Ok, wusste ich nicht.
BlackJack hat geschrieben:Die Klammern bei den ``print``-Anweisungen sind irreführend. Das ist in Python <3 keine Funktion. Und Python 3.x kann es nicht sein, weil es dort den Namen `raw_input()` nicht mehr gibt. ``return`` ist ebenfalls keine Funktion.
Ich verwende auch noch kein Python 3.x, habe mir aber schon mal angewohnt, 'print' als Funktion zu notieren. Auch wenn aus 'raw_input()' ab 3.x 'input()' wird, will ich das allerdings noch nicht ersetzen, da von 'raw_input()' zu 'input()' mehr passiert als von 'print' zu 'print()'. Aber vielleicht sollte ich mich wirklich auf entweder oder beschränken...?
BlackJack hat geschrieben:...ist das Löschen des Inhalts aber unüblich und auch nicht nett...
Geb' ich Dir Recht, aber in dem Fall ist soviel Menütext, Bestätigungstext, Eingabetext etc. pp dabei, dass ich es übersichtlicher finde, wenn gelöscht wird. Aber das kann man sicherlich auch anderst sehen...
BlackJack hat geschrieben:Die `status()`-Funktion erscheint mir überflüssig.
Mir auch... :-)
BlackJack hat geschrieben:...und die ``if``/``elif``-Kaskade könnte man durch ein Dictionary oder in diesem Fall auch eine Liste ersetzen.
Das ist cool, hab' ich gleich geändert....!!
BlackJack hat geschrieben:...so dass man für eine weitere Berechnungsart das Programm nur noch an *einer* Stelle um einen entsprechenden Datensatz erweitern muss...
Habe ich jetzt mal gemacht. Aber vom Gefühl her scheint mir 'lambda' hier irgendwie nicht das Richtige zu sein, oder? Es sollte eine Möglichkeit geben, lediglich eine Rechenformel ablegen zu können, die dann mit veränderten Parametern aufgerufen werden kann. Ich hing' schon am operator-Modul, wollte quasi sowas wie

Code: Alles auswählen

formel = operator.mul(a, b, c)
Allerdings komm' ich nicht darauf, wie man sowas in ein dict oder ähnliches ablegen kann, wenn a, b und c noch gar nicht existieren.

Oder ist 'lambda' doch der Weg zum Glück?

Hier also mal die Änderung:

Code: Alles auswählen

# -*- coding: utf-8 -*-

import os
import math

AUSWAHL_TXT = (('Flächen', 'Vierecks'),
    ('Volumen', 'Quaders'),
    ('Flächen', 'Kreises'),
    ('Flächen', 'Dreiecks'))
STATUS_TXT = ('Ihre Auswahl: ',
    'OOPS! Falsche Eingabe! Bitte wählen Sie zwischen 1 und 4: ')
BERECHNUNGEN = {0:(('Erste Seite:  ', 'Zweite Seite: '),
        lambda value: 'Der Flächeninhalt beträgt: %f' % 
        (value[0] * value[1])),
        1:(('Länge:  ', 'Breite: ', 'Höhe:   '),
        lambda value: 'Das Volumen des Quaders beträgt: %f' %
        (value[0] * value[1] * value[2])),
        2:(('Radius: ', ),
        lambda value: 'Der Flächeninhalt des Kreises beträgt: %f' %
        ((value[0] * value[0]) * math.pi)),
        3:(('Länge: ', 'Höhe:  '),
        lambda value: 'Der Flächeninhalt des Dreiecks beträgt: %f' %
        (0.5 * value[0] * value[1]))}

def menue():
    if os.name == 'nt':
        command = 'cls'
    else:
        command = 'clear'
    os.system(command)
    print("Wilkommen zum Programm fuer die Flaechen/Volumenberechnung")
    print("von Formen und Koerpern.\n")
    print("Bitte waehlen sie aus der folgenden Liste welche Berechnung")
    print("sie durchfuehren moechten\n")
    print("Benutzerhinweis : Anstatt die ueblichen Kommata (,) benutzen")
    print("sie bitte Punkte (.) !\n\n")
    print("1 = Flaechenberechnung eines Vierecks ")
    print("2 = Volumenberechnung eines Quaders ")
    print("3 = Flaechenberechnung eines Kreises ")
    print("4 = Flaechenberechnung eines Dreiecks\n")
    print("0 = Ende\n")

def bestaetigung(auswahl):
    print("\nSie haben sich für die %sberechnung eines %s entschieden." %
        (AUSWAHL_TXT[auswahl][0], AUSWAHL_TXT[auswahl][1]))

def berechnung(auswahl):
    value = []
    for eingabe in BERECHNUNGEN[auswahl][0]:
        value.append(float(raw_input(eingabe)))
    print(BERECHNUNGEN[auswahl][1](value))

def main():
    status = 0
    while True:
        menue()
        auswahl = int(raw_input(STATUS_TXT[status]))
        if auswahl == 0:
            print('\nOver and out.')
            break
        if 0 < auswahl <= len(BERECHNUNGEN): 
            bestaetigung(auswahl-1)
            berechnung(auswahl-1)
            raw_input()
        else:
            status = 1

if __name__ == '__main__':
    main()
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@mutetella: Du kannst ``print`` in Python <3 nicht als Funktion benutzen. Die Klammern machen da keinen Funktionsaufruf draus. Insbesondere funktioniert das nicht mehr wenn Du mehrere Werte durch Kommas getrennt ausgeben willst, dann wird bei der ``print``-Anweisung daraus nämlich ein Tupel wenn Klammern drum herum sind.

``lambda`` ist da schon eine gute Idee wenn man kurze Formeln speichern will. Ich hätte die aber wirklich nur zum Berechnen des Ergebnisses verwendet, dann kann man das später vielleicht auch in einer GUI wiederverwenden, wenn das Ergebnis nicht als Satz sondern vielleicht nur in einer Textbox ausgegeben werden soll.

Das Menü ist noch unabhängig von der Datenstruktur und müsste zusätzlich erweitert werden, wenn man noch etwas hinzufügt.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Hmm... hab' ja schon ein bischen ein schlechtes Gewissen, weil ich nevergod hier einfach seinen Thread übernehme. Ich hoffe, er sieht mir das nach... :)
BlackJack hat geschrieben:Die Klammern machen da keinen Funktionsaufruf draus.
Ich dachte, 'print' ist seit 2.5/2.6 (weiß net genau) sowohl als Funktion wie auch als Anweisung implementiert. Aber wenn man nur 2 Meter weiterdenkt... Wäre ja so, wie ich mir das wieder mal vorstelle, auch nicht möglich... Aber geändert hab' ich's jetzt nicht mehr, bin ich zu faul... ;-)
BlackJack hat geschrieben:Ich hätte die aber wirklich nur zum Berechnen des Ergebnisses verwendet, ...
Stimmt, da bin ich ja schon wieder bei meinem aktuellen MVC-Thema... :-)
BlackJack hat geschrieben:Das Menü ist noch unabhängig von der Datenstruktur...
Jepp...

BlackJack hat geschrieben:``lambda`` ist da schon eine gute Idee wenn man kurze Formeln speichern will.
Und wenn man "tiefer" einsteigen möchte? Welche Möglichkeit gibt es, um umfangreichere Berechnungen zu speichern. Wenn sich z. B. der User seine eigenen Formeln zusammenfügen und diese dann für spätere Verwendungen abspeichern kann?
Könntest Du mir da ein Stichwort geben?

Gruß
mutetella


Hier noch die Änderung:

Code: Alles auswählen

# -*- coding: utf-8 -*-

import os
import math

BERECHNUNGEN = {0:{'title':'Flächenberechnung eines Vierecks',
    'values':('Erste Seite:  ', 'Zweite Seite: '),
    'operation':lambda value: (value[0] * value[1])},
    1:{'title':'Volumenberechnung eines Quaders',
    'values':('Länge:  ', 'Breite: ', 'Höhe:   '),
    'operation':lambda value: (value[0] * value[1] * value[2])},
    2:{'title':'Flächenberechnung eines Kreises',
    'values':('Radius: ', ),
    'operation':lambda value: ((value[0] * value[0]) * math.pi)},
    3:{'title':'Flächenberechnung eines Dreiecks',
    'values':('Länge: ', 'Höhe:  '),
    'operation':lambda value: (0.5 * value[0] * value[1])}}
STATUS_TXT = ('Ihre Auswahl: ',
    'OOPS! Falsche Eingabe! Bitte wählen Sie zwischen 1 und %i: ' %
    (len(BERECHNUNGEN)))

def menue():
    if os.name == 'nt':
        command = 'cls'
    else:
        command = 'clear'
    os.system(command)
    print("Wilkommen zum Programm fuer die Flaechen/Volumenberechnung")
    print("von Formen und Koerpern.\n")
    print("Bitte waehlen sie aus der folgenden Liste welche Berechnung")
    print("sie durchfuehren moechten\n")
    print("Benutzerhinweis : Anstatt die ueblichen Kommata (,) benutzen")
    print("sie bitte Punkte (.) !\n\n")
    for i in xrange(len(BERECHNUNGEN)):
        print('%i = %s' % (i+1, BERECHNUNGEN[i]['title']))
    print("0 = Ende\n")

def bestaetigung(auswahl):
    print("\nSie haben sich für die %s entschieden." %
        (BERECHNUNGEN[auswahl]['title']))

def berechnung(auswahl):
    value = []
    for eingabe in BERECHNUNGEN[auswahl]['values']:
        value.append(float(raw_input(eingabe)))
    print('Das Ergebnis der %s lautet %f' %
        (BERECHNUNGEN[auswahl]['title'], 
        BERECHNUNGEN[auswahl]['operation'](value)))

def main():
    status = 0
    while True:
        menue()
        auswahl = int(raw_input(STATUS_TXT[status]))
        if auswahl == 0:
            print('\nOver and out.')
            break
        if 0 < auswahl <= len(BERECHNUNGEN): 
            bestaetigung(auswahl-1)
            berechnung(auswahl-1)
            raw_input()
        else:
            status = 1

if __name__ == '__main__':
    main()
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@mutetella: Wenn Der Benutzer eigene Formeln erstellen können soll, dann müsste man erst einmal klarstellen wie das genau vor sich gehen soll. Wenn es darauf hinausläuft, dass er was eingibt, was dann mit `eval()` ausgewertet wird, kann man ihm auch gleich sagen wie er das Programm in Python erweitert. Wenn es kontrollierter ausgeführt werden soll und auch so etwas passieren soll wie: Benutzer gibt Formel ein und Programm fragt nach den Bedeutungen/Beschreibungen der verwendeten Variablennamen, dann muss man sich einen Parser für mathematische Ausdrücke schreiben. Das ist dann schon etwas aufwändiger.

Für meinen Geschmack hast Du zu viele und zu lang verkettete Index- bzw. Schlüsselzugriffe im Quelltext. Und anstelle von Dictionaries könnte man hier IMHO schon eine Klasse sinnvoll einsetzen um die Berechnungen zu beschreiben.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

BlackJack hat geschrieben:@mutetella: Du kannst ``print`` in Python <3 nicht als Funktion benutzen.
Also

Code: Alles auswählen

from __future__ import print_function
geht auch schon vor 3.x.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Ok, hab' das dict durch eine Klasse ersetzt. Zudem hab' ich noch kleinere Formatierungen eingebaut, deswegen die decode()-Sachen, weil len('ä') etc. sonst falsche Werte zurückgibt. Wir Deutschen haben es schon schwer... ;-) Zuerst hatte ich bereits beim Ablegen der Texte in Formula() alles decodiert. Hatte dann aber das Problem, dass raw_input() keinen utf8-decodierten Prompt aus Formula() akzeptiert. Hätte also dann wieder zurückcodieren müssen. Auch blöd.
Bin mir einfach nicht sicher, ob es nicht einen sinnigeren Weg gäbe...
BlackJack hat geschrieben:...zu lang verkettete Index- bzw. Schlüsselzugriffe...
Bin mir nicht sicher, was Du meinst. Findest Du ein dict mit dict's als values schon zu viel? Ok, in diesem Fall ist eine Klasse in jedem Fall eleganter. Ich verwende aber dict's gerne zum Ablegen von config-Parametern oder auch zum Cachen. Und hab' ich schnell mal 2 - 3 Ebenen. Nicht so dolle, oder?

Gruß
mutetella

Code: Alles auswählen

# -*- coding: utf-8 -*-

import os

formulas = []

class Formula(object):
    counter = 0
    def __init__(self, title, values, formula):
        self.title = title
        self.values = values
        self.formula = formula
        Formula.counter += 1

    def calc(self, value):
        return eval(self.formula)

def menue(status):
    if os.name == 'nt':
        command = 'cls'
    else:
        command = 'clear'
    os.system(command)
    status_txt = ('Ihre Auswahl: ',
        'OOPS! Falsche Eingabe! Bitte wählen Sie zwischen 1 und %i: ' %
        (Formula.counter))
    print("Wilkommen zum Programm fuer die Flaechen/Volumenberechnung")
    print("von Formen und Koerpern.\n")
    print("Bitte waehlen sie aus der folgenden Liste welche Berechnung")
    print("sie durchfuehren moechten\n")
    print("Benutzerhinweis : Anstatt die ueblichen Kommata (,) benutzen")
    print("sie bitte Punkte (.) !\n")
    for i in xrange(Formula.counter):
        print('%i = %s' % (i+1, formulas[i].title))
    print('\n-1 = Formel hinzufügen')
    print(' 0 = Ende\n')
    return int(raw_input(status_txt[status]))

def bestaetigung(choice):
    title_length = len(formulas[choice].title.decode('utf-8'))
    print('\n%s\n%s\n' %
        (formulas[choice].title,
        title_length * '-'))

def berechnung(choice):
    value = []
    r_margin = len(sorted(
        [v.decode('utf-8') for v in formulas[choice].values], 
        key=len)[-1]) + 1
    for eingabe in formulas[choice].values:
        eingabe = eingabe + (r_margin - len(eingabe.decode('utf-8'))) * ' '
        value.append(float(raw_input(eingabe)))
    print('\nErgebnis: %f' %
        (formulas[choice].calc(value)))

def add_formula(title=None, values=None, formula=None):
    if title == values == formula == None:
        counter = 0
        values = []
        title = raw_input('Formeltitel: ')
        while True:
            value = raw_input('Name für value[%i]: '% (counter))
            counter += 1
            if value == '':
                break
            values.append(value)
        formula = raw_input('Formel: ')
    formulas.append(Formula(title, values, formula))

def choice(status=0):
    while True:
        choice = menue(status)
        if choice == 0:
            print('\nOver and out.')
            break
        elif choice == -1:
            add_formula()
        elif 0 < choice <= Formula.counter: 
            bestaetigung(choice - 1)
            berechnung(choice - 1)
            raw_input()
            status = 0
        else:
            status = 1

def main():
    DUMMY = (('Flächenberechnung eines Vierecks',
            ['Erste Seite:', 'Zweite Seite:'],
            'value[0] * value[1]'),
            ('Volumenberechnung eines Quaders',
            ['Länge:', 'Breite:', 'Höhe:'],
            'value[0] * value[1] * value[2]'),
            ('Flächenberechnung eines Kreises',
            ['Radius:'],
            '(value[0] * value[0]) * 3.1415926535897931'),
            ('Flächenberechnung eines Dreiecks',
            ['Länge:', 'Höhe:'],
            '0.5 * value[0] * value[1]'))

    for title, values, formula in DUMMY:
        add_formula(title, values, formula)

    choice()
    
if __name__ == '__main__':
    main()
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@mutetella: `Formula.counter` ist keine gute Idee. Damit wird in der Klasse eine Information gespeichert, die eigentlich zu dem Container gehört in den man die Objekte steckt, und die dort ja auch via `len()` verfügbar ist. Auf der Klasse sorgt das dafür, dass die Klasse nicht so flexibel wiederverwendbar ist. Zum Beispiel könnte man die Objekte ja via `pickle` in eine Datei speichern und später wieder laden. Dann könnte der Benutzer Formelsammlungen zu verschiedenen Themengebieten anlegen. In dem Falle funktioniert so ein "globaler" Zähler aber nicht mehr.

Zu `eval()` sag ich jetzt mal nichts. :-)

Was die Kodierungen angeht, wären Unicode-Literale schon der richtige Weg, allerdings muss man dann Zeichenketten sowohl bei der Aus- als auch bei der Eingabe entsprechend umkodieren.

Die Berechnung von `r_margin` erscheint mir ein wenig kompliziert. Schau Dir mal die `max()`-Funktion an. Und für die Formatierung der `eingabe` wozu man bei Zeichenkettenformatierung mittels ``%`` den '*' benutzen kann.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

BlackJack hat geschrieben:`Formula.counter` ist keine gute Idee.
Jetzt wollte ich gleich mal anwenden, worüber ich in meinem 'Methoden-Attribut'-Thread bereits so einiges, auch von Dir, gelernt habe. Nun ja, und dann gleich ein Griff ins Klo... :-( Aber mir ist klar, warum das in diesem Fall nicht so geschickt ist.
BlackJack hat geschrieben:Zu `eval()` sag ich jetzt mal nichts. :-)
Doch, bitte! Ich hab' bereits eine Idee für ein Feature in meinem Kalenderprogramm, das in eine ähnliche Richtung gehen soll, wie die Formelgeschichte hier...
BlackJack hat geschrieben:Was die Kodierungen angeht, wären Unicode-Literale schon der richtige Weg, allerdings muss man dann Zeichenketten sowohl bei der Aus- als auch bei der Eingabe entsprechend umkodieren.
Du meinst also, bevor Literale abgelegt werden (wo auch immer), erstmal mit decode in Unicode-Literale umwandeln und bei Verwendung dann wieder encoden?
BlackJack hat geschrieben:Die Berechnung von `r_margin` erscheint mir ein wenig kompliziert.
Das liegt daran, dass die Berechnung von 'r_margin' ein wenig kompliziert ist. :-)
BlackJack hat geschrieben:Schau Dir mal die `max()`-Funktion an.
O Mann, genau sowas hab' ich gesucht...
BlackJack hat geschrieben:...bei Zeichenkettenformatierung mittels ``%`` den '*' benutzen kann.
Is cool man... Ich muss mal dringend die built-in Funktionen anschauen. Man überfliegt sowas ja meist nur, aber da sind richtige Schätze drin....

Noch 'ne ganz andere Frage:
Was hat es eigentlich mit ``xxx``, `xxx` oder 'xxx' auf sich?

Ich stell' jetzt das Programm nochmal komplett rein, auch wenn's den Thread langsam groß macht...

Code: Alles auswählen

# -*- coding: utf-8 -*-

import os

formulas = []

class Formula(object):
    def __init__(self, title, values, formula):
        self.title = title
        self.values = values
        self.formula = formula

    def calc(self, value):
        return eval(self.formula)

def menue(status):
    if os.name == 'nt':
        command = 'cls'
    else:
        command = 'clear'
    os.system(command)
    status_txt = ('Ihre Auswahl: ',
        'OOPS! Falsche Eingabe! Bitte wählen Sie zwischen 1 und %i: ' %
        (len(formulas)))
    print("Wilkommen zum Programm fuer die Flaechen/Volumenberechnung")
    print("von Formen und Koerpern.\n")
    print("Bitte waehlen sie aus der folgenden Liste welche Berechnung")
    print("sie durchfuehren moechten\n")
    print("Benutzerhinweis : Anstatt die ueblichen Kommata (,) benutzen")
    print("sie bitte Punkte (.) !\n")
    for i in xrange(len(formulas)):
        print('%i = %s' % (i+1, formulas[i].title))
    print('\n-1 = Formel hinzufügen')
    print(' 0 = Ende\n')
    return int(raw_input(status_txt[status]))

def bestaetigung(choice):
    title_length = len(formulas[choice].title.decode('utf-8'))
    print('\n%s\n%s\n' %
        (formulas[choice].title,
        title_length * '-'))

def berechnung(choice):
    value = []
    r_margin = len(max(formulas[choice].values)) + 1
    for eingabe in formulas[choice].values:
        gap = r_margin - len(eingabe.decode('utf-8'))
        eingabe = '%s%*s' % (eingabe, gap, ' ')
        value.append(float(raw_input(eingabe)))
    print('\nErgebnis: %f' %
        (formulas[choice].calc(value)))

def add_formula(title=None, values=None, formula=None):
    if title == values == formula == None:
        counter = 0
        values = []
        title = raw_input('Formeltitel: ')
        while True:
            value = raw_input('Name für value[%i]: '% (counter))
            counter += 1
            if value == '':
                break
            values.append(value)
        formula = raw_input('Formel: ')
    formulas.append(Formula(title, values, formula))

def choice(status=0):
    while True:
        choice = menue(status)
        if choice == 0:
            print('\nOver and out.')
            break
        elif choice == -1:
            add_formula()
        elif 0 < choice <= len(formulas): 
            bestaetigung(choice - 1)
            berechnung(choice - 1)
            raw_input()
            status = 0
        else:
            status = 1

def main():
    DUMMY = (('Flächenberechnung eines Vierecks',
            ['Erste Seite:', 'Zweite Seite:'],
            'value[0] * value[1]'),
            ('Volumenberechnung eines Quaders',
            ['Länge:', 'Breite:', 'Höhe:'],
            'value[0] * value[1] * value[2]'),
            ('Flächenberechnung eines Kreises',
            ['Radius:'],
            '(value[0] * value[0]) * 3.1415926535897931'),
            ('Flächenberechnung eines Dreiecks',
            ['Länge:', 'Höhe:'],
            '0.5 * value[0] * value[1]'))

    for title, values, formula in DUMMY:
        add_formula(title, values, formula)

    choice()
    
if __name__ == '__main__':
    main()
Gruß
mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@mutetella: `eval()` finde ich halt "evil". :-)

Literale heissen die Zeichenfolgen *im Quelltext* für bestimmte Datentypen, für die es Syntax gibt um Konstanten von ihnen direkt zu schreiben. Also zum Beispiel Zahlen oder Zeichenketten. Zur Laufzeit kann man also nichts in ein Literal umwandeln. Ich meinte dass man wenn man mit Unicode arbeitet, das schon von Anfang an konsequent tun sollte. Also nicht ``'hällö'.decode('utf-8')`` sondern gleich ein Unicode-Literal in den Quelltext: ``u'hällö'``.

Jetzt musst Du `max()` nur noch richtig einsetzen:

Code: Alles auswählen

In [835]: len(max(['aa', 'z']))
Out[835]: 1

In [836]: max(['aa', 'z'], key=len)
Out[836]: 'aa'

In [837]: len(max(['aa', 'z'], key=len))
Out[837]: 2
Ich verwende bei Texten meistens reStructuredText als Auszeichnung, auch wenn das Medium das eigentlich gar nicht unterstützt. Darum die ``x`` und `x`. :-)

Zum Quelltext: `berechung()` könnte man gleich das ausgewählte `Formula`-Exemplar übergeben, dann braucht man dort nicht auf das globale `formulas` zurückgreifen.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

BlackJack hat geschrieben:`eval()` finde ich halt "evil". :-)
Aus denselben Gründen wie bei 'input()'? Denn über die Funktion 'add_Formula()' geschieht ja letztlich nichts anderes als ein 'raw_input(eval())', das wiederum einem 'input()' entspricht. Oder gibt es noch andere Gründe?
BlackJack hat geschrieben:Literale heissen die Zeichenfolgen *im Quelltext*...
Ok, das wusste ich nicht...
Ich denke mal, die Unicode-Geschichte wird mich immer wieder beschäftigen, aber bitte nicht heute... :-)
BlackJack hat geschrieben:Jetzt musst Du `max()` nur noch richtig einsetzen
Ich hasse es, wenn ich so schlampig bin... :-(
Aber es steckt auch eine gewisse Fiesheit dahinter, dass 'a' < 'z' ist.
BlackJack hat geschrieben:Ich verwende bei Texten meistens reStructuredText als Auszeichnung, ...
Ich werde mich jetzt NICHT mit reSructuredText beschäftigen... Nein, nein, nein... Aber den Link behalt' ich... ;-)
BlackJack hat geschrieben:`berechung()` könnte man gleich das ausgewählte `Formula`-Exemplar übergeben, ...

Code: Alles auswählen

def berechnung(formula):
    value = []
    r_margin = len(max(formula.values, key=len)) + 1
    for eingabe in formula.values:
        gap = r_margin - len(eingabe.decode('utf-8'))
        eingabe = '%s%*s' % (eingabe, gap, ' ')
        value.append(float(raw_input(eingabe)))
    print('\nErgebnis: %f' %
        (formula.calc(value)))
Warum? Wegen MVC? Wäre es sinnvoller, kein globales 'formulas' zu verwenden? Dieses nach dem Anlegen und Befüllen jeweils weiterzureichen?

Gruß
mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Antworten