Mehrere Anfängerfragen ("GoTo", Eingabe beschränken, array?)

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
banthrass
User
Beiträge: 14
Registriert: Mittwoch 1. Februar 2006, 13:48

Hallo zusammen,

mein erstes Projekt ist ein Taschenrechner:

Frage 1:
Nun würde ich gerne die Eingabe in int(input("bla bla: ")) auf bestimmt zeichen beschränken. Also es sollen nur zahlen erlaubt sein. bei allem anderen soll eine Meldung kommen.

Frage 2:
Mittlerweile weiß ich, dass es kein Goto gibt. Ich habe auch alternativen Code gefunden der funktionieren soll, wie goto. Leider hab ich ihn noch nicht verstanden. Kann mir da mal einer was zu sagen? Also was nutze ich statt Goto und wie. Im Grunde will ich, dass wenn eine Rechnung beendet wurde man wieder ins Menü, also an den Anfang des Programms kommt.

Frage 3:

Ich würde gerne ein 'Abfrage machen, wieviel zahlen man vielleicht multiplizieren will. Wenn jetzt der User schreib er will 4. Wie erstelle ich dann entsprechend seiner Eingabe variablen? oder mach ich sowas dann in einem Array?

Hier mal mein Code bisher. Für Tips und Anregungen bin ich offen. Danke

Code: Alles auswählen

choice = 0
zahl_1 = 0
zahl_2 = 0
zahl_3 = 0
zahl_4 = 0

print ("""Menü
        1. addieren
        2. subtrahieren
        3. multiplizieren
        4. dividieren""")

choice=int(input("Auswahl: "))

if choice == 1 :
    print ("Bitte stellen Sie nun Ihre Aufgabe")

    zahl_1 = int(input("Erste Zahl: "))
    zahl_2 = int(input("Zweite Zahl: "))

    result = zahl_1 + zahl_2
    print ("Das Ergebnis lautet: ", result)

elif choice == 2 :
    print ("Bitte stellen Sie nun Ihre Aufgabe")

    zahl_1 = int(input("Erste Zahl: "))
    zahl_2 = int(input("Zweite Zahl: "))

    result = zahl_1 - zahl_2
    print ("Das Ergebnis lautet: ", result)

elif choice == 3 :
    print ("Bitte stellen Sie nun Ihre Aufgabe")

    zahl_1 = int(input("Erste Zahl: "))
    zahl_2 = int(input("Zweite Zahl: "))

    result = zahl_1 * zahl_2
    print ("Das Ergebnis lautet: ", result)

elif choice == 4 :
    print ("Bitte stellen Sie nun Ihre Aufgabe")

    zahl_1 = int(input("Erste Zahl: "))
    zahl_2 = int(input("Zweite Zahl: "))

    result = zahl_1 / zahl_2
    print ("Das Ergebnis lautet: ", result)

else :
    print ("Ihr Eingabe ist ungültig")
       
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Ad 1: `int(input)` beschraenkt das schon auf Zahlen, wenn du auch floats willst solltest du `float` statt `int` nehmen (Da gab es neulich auch einen Snippet im Forum). Sind das keine Zahlen, wird eine Exception geworfen.
Edit: Snippet

Ad 2: Du willst Funktionen für Menue, etc nutzen.

Code: Alles auswählen

def print_menu():
    print(...)

def main():
    while True:
        print_menu()
        selection = input(...)
        if selection in set(("q", "quit")):
            break
        elif selection = ...

Ad 3: Jein, du willst Listen und keine Arrays.
Zuletzt geändert von cofi am Mittwoch 28. Juli 2010, 16:03, insgesamt 1-mal geändert.
BlackJack

@banthrass: Ad 1) Das geht so nicht. Du könntest höchstens nach der Eingabe überprüfen ob sie etwas verbotenes enthält und darauf entsprechend reagieren. Plattformspezifisch kann man sich da zwar sicher etwas hinbasteln, aber das möchte man eigentlich nicht. Schon gar nicht als Anfänger.

Ad 2) Denke nicht in direkten Sprüngen, sondern in Wiederholungen. Die drückt man mit Schleifen aus. Du willst also das Hauptmenü solange wiederholen bis irgendeine Bedingung eintritt. Das geht mit ``while``.

Ad 3) Das macht man dann mit Listen. Ich würde auch nicht vorher fragen, sondern eine Eingabe definieren, die als Ende gilt, also zum Beispiel die leere Eingabe als Zeichen dass die bis dahin eingegebenen Zahlen addiert/multipliziert/… werden sollen.

Zum Quelltext: `zahl_3` und `zahl_4` werden nicht verwendet und man braucht und sollte die Namen nicht so vorbelegen wie Du das am Anfang gemacht hast.

Der Quelltext enthält sehr viele Wiederholungen, die sich im Grunde nur in der Rechenoperation unterscheiden. Das kann man in einer Funktion zusammenfassen, welche die Operation als Argument übergeben bekommt. Die Operatoren gibt es im Modul `operator` alle als Funktionen.

Es sollte kein Code auf Modulebene stehen ausser Definitionen von Konstanten, Klassen, und Funktionen. Gewöhn Dir gleich an den Quelltext ordentlich auf Funktionen aufzuteilen.

Code: Alles auswählen

from operator import add, sub, mul, div


def calculate(func):
    print 'Bitte stellen Sie nun Ihre Aufgabe'

    zahl_1 = int(raw_input(' Erste Zahl: '))
    zahl_2 = int(raw_input('Zweite Zahl: '))

    print 'Das Ergebnis lautet:', func(zahl_1, zahl_2)


def main():
    operations = [('addieren', add),
                  ('subtrahieren', sub),
                  ('multiplizieren', mul),
                  ('dividieren', div)]
    print 'Menü'
    for i, (text, _func) in enumerate(operations):
        print '%d. %s' % (i + 1, text)
    
    choice = int(raw_input('Auswahl: ')) - 1
    try:
        _text, func = operations[choice]
    except IndexError:
        print 'Ihre Eingabe ist ungültig.'
    else:
        calculate(func)


if __name__ == '__main__':
    main()
problembär

Ein Taschenrechner in Python macht keinen Sinn, weil man einfach den interaktiven Modus dazu verwenden kann: Da kann man z.B.

Code: Alles auswählen

>>> print 2 ** 3 - 25.3 * 17. / 25.
usw. eingeben.
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

problembär hat geschrieben:Ein Taschenrechner in Python macht keinen Sinn, weil man einfach den interaktiven Modus dazu verwenden kann: Da kann man z.B.

Code: Alles auswählen

>>> print 2 ** 3 - 25.3 * 17. / 25.
usw. eingeben.
Naja, gerade zur Einführung ist das doch trotzdem ideal. An diesem Thread hier sieht man ja, dass auch grundlegende Fragen noch geklärt werden sollen - etwa Programmieren ohne Spaghetti-Code.

Ich finde das Taschenrechner-Ding ist eine gute Sache, führt schnell zu Ergebnissen und ist ein lebensnahes Beispiel. Jeder weiß direkt, was man da vll. gerne haben will und kann den Rechner entsprechend erweitern. Da geht es jetzt nicht unbedingt darum, dass/ob man sowas auch in der interaktiven Shell machen kann.

Gruß,

brb

//edit:
Also bei näherer Betrachtung finde ich den Taschenrechner geradezu ideal für den Einstieg: Es geht halt darum, einen intelligenten und ökonomischen Programmfluss um ein Szenario drumherum zu konstruieren, das vorher klar abgrenzbar und absehbar ist. Dabei kann er sich mit Inputs, If-Abfragen, Schleifen und mathematischen Operatoren auseinandersetzen.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Barabbas hat geschrieben://edit:
Also bei näherer Betrachtung finde ich den Taschenrechner geradezu ideal für den Einstieg: Es geht halt darum, einen intelligenten und ökonomischen Programmfluss um ein Szenario drumherum zu konstruieren, das vorher klar abgrenzbar und absehbar ist. Dabei kann er sich mit Inputs, If-Abfragen, Schleifen und mathematischen Operatoren auseinandersetzen.
Das kommt sehr stark darauf an was man mit Taschenrechner meint, spontan würde ich persönlich etwas in dieser Richtung erwarten.

Code: Alles auswählen

# coding: utf-8
import re

class SymbolBase(object):
    id = None
    first = second = None
    lbp = 0

    def __init__(self, parser, value):
        self.parser = parser
        self.value = value

    def nud(self):
        raise SyntaxError('syntax error')

    def led(self, left):
        raise SyntaxError('unknown operator')

    def __repr__(self):
        out = self.first, self.second
        out = [self.id] + (map(str, filter(None, out)) or [self.value])
        return '({0})'.format(' '.join(out))

class Parser(object):
    def __init__(self):
        self.symbol_table = {}

    def add_symbol(self, id, bp=0):
        symbol_cls = self.symbol_table.get(id)
        if not symbol_cls:
            self.symbol_table[id] = symbol_cls = type(
                'Symbol',
                (SymbolBase, ),
                dict(id=id, lbp=bp)
            )
        symbol_cls.lbp = max([symbol_cls.lbp, bp])
        return symbol_cls

    def add_infix(self, id, bp):
        symbol_cls = self.add_symbol(id, bp)
        def led(self, left):
            self.first = left
            self.second = self.parser.parse_expression(self.lbp)
            return self
        symbol_cls.led = led
        return symbol_cls

    def add_infix_r(self, id, bp):
        symbol_cls = self.add_symbol(id, bp)
        def led(self, left):
            self.first = left
            self.second = self.parser.parse_expression(self.lbp)
            return self
        symbol_cls.led = led
        return symbol_cls

    def add_prefix(self, id, bp):
        symbol_cls = self.add_symbol(id, bp)
        def nud(self):
            self.first = self.parser.parse_expression(self.lbp)
            self.second = None
            return self
        symbol_cls.nud = nud
        return symbol_cls

    def next_symbol(self):
        id, value = self._tokenizer.next()
        try:
            symbol_cls = self.symbol_table[id]
        except KeyError:
            raise SyntaxError('unknown token {0}'.format(id))
        self.symbol = symbol_cls(self, value)

    def expect_symbol(self, id):
        if self.symbol.id != id:
            raise ParserError(
                'expected symbol {0}, got {1}'.format(id, self.symbol.id)
            )
        self.next_symbol()

    def parse(self, tokenizer):
        self._tokenizer = tokenizer
        self.next_symbol()
        return self.parse_expression()

    def parse_expression(self, rbp=0):
        left_symbol = self.symbol
        self.next_symbol()
        left = left_symbol.nud()
        while rbp < self.symbol.lbp:
            left_symbol = self.symbol
            self.next_symbol()
            left = left_symbol.led(left)
        return left

math_parser = Parser()
math_parser.add_symbol('number').nud = lambda x: x
math_parser.add_symbol(')').nud = lambda x: x
math_parser.add_symbol('end').nud = lambda x: x
math_parser.add_infix('+', 10)
math_parser.add_infix('-', 10)
math_parser.add_infix('*', 20)
math_parser.add_infix('/', 20)
math_parser.add_infix_r('**', 30)
math_parser.add_prefix('+', 40)
math_parser.add_prefix('-', 40)
math_parser.add_prefix('(', 50)

def set(id, name):
    def decorate(func):
        setattr(math_parser.symbol_table[id], name, func)
        return func
    return decorate

@set('(', 'nud')
def nud(self):
    self.first = self.parser.parse_expression()
    self.parser.expect_symbol(')')
    return self

math_re = re.compile(ur'(\d+)|(\*\*|\*|/|\+|\-|\(|\))')

def tokenize(string):
    for number, operator in math_re.findall(string):
        if number:
            yield 'number', number
        else:
            yield operator, operator
    yield 'end', 'end'

def parse(string):
    return math_parser.parse(tokenize(string))
Die Interpretation des ASTs überlasse ich mal dem engagierten Leser ;)
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Da stimmen aber die Prioritäten nicht ganz ;)

Code: Alles auswählen

5*8 - 3:
(* (number 5) (- (number 8) (number 3)))
Sollte eher sein

Code: Alles auswählen

(- (* (number 5) (number 8)) (number 3))
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Bei den add_ Methoden self.lbp durch bp ersetzen und es sollte funktionieren.
banthrass
User
Beiträge: 14
Registriert: Mittwoch 1. Februar 2006, 13:48

Danke für die vielen Infos. Ich will einfach mit dem Rechner starten, weil ich es sinnvoll finde. Kann ihn ja ohne Ende ausbauen. Die gegeben Tips versuche ich umzusetzen. Bastel grad die wiederholung vom Menü und versuche eine Fehlermeldung auszuwerfen wenn man statt zahlen Buchstaben eingibt. Funtzt noch nicht wirklich. Kommt aber sicher noch :D
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Das ist doch ganz einfach:

Code: Alles auswählen

>>> try:
...     int("Hallo")
... except ValueError as e:
...     print("Error! %r is not a number" % "Hallo")
... 
Error! 'Hallo' is not a number
Sinnvoll ist hier auch der `else`-Zweig von `try`, der ausgefuehrt wird, wenn es keine Ausnahme gab. Einfach nach dem `except`-Zweig schreiben.
ZEins
User
Beiträge: 2
Registriert: Donnerstag 29. Juli 2010, 21:43

Hallo,
das mit dem try ist eine gute Sache, der Rest ist vielleicht etwas kompliziert.
Wenn du das Programm neu starten möchtest, funktioniert das hier vielleicht:
Schreibe am Anfang des Programmes:

Code: Alles auswählen

while True:
beachte dabei, dass alles darunter eingerückt werden muss.

Am Ende des Programmes ist, denke ich mir mal, eine Abfrage, ob das Programm nochmal ausgeführt werden soll. Sagt der Benutzer "Nein", sollte es so aussehen:

Code: Alles auswählen

if restart == 'n':
    break
Du kannst eine genauere Unterscheidung mit elif machen, damit bei einer fehlerhaften Eingabe das Programm nicht neu startet, wie beispielsweise:

Code: Alles auswählen

if restart == 'n':
    break
elif restart == 'j';
    continue
else:
    restart = raw_input("Ihre Eingabe war nicht eindeutig. Bitte versuchen Sie es erneut!")
wobei bei Umsetzung des else-Zweiges eine weitere while-Schleife mit der Bedingung "True" unabdingbar ist.

Aus Sicherheitsgründen solltest du auch von input() Abstand nehmen. Gehe mal in den interaktiven Modus, gebe dort

Code: Alles auswählen

input("Gebe irgendwas ein: ")
und wenn du danach zur Eingabe gebeten wirst, gebe einfach mal

Code: Alles auswählen

print 'Test'
ein. Es erscheint eine Fehlermeldung, die einen falschen Syntax meldet.
Um das zu verhindern, solltest du IMMER raw_input() verwenden.
Denn wenn du

Code: Alles auswählen

raw_input("Gebe irgendwas ein: ")
verwendest und dahinter, bei Abfrage

Code: Alles auswählen

print 'Test'
schreibst, wird genau das ausgegeben, was du eingegeben hast.

Achja, übrigens noch:
Derzeit würde dir dein Programm bei der Berechnung von 2 / 3 0 ausgeben. Das liegt daran, dass das Ergebnis einer Division einer Zahl ohne Dezimalpunkt durch eine Zahl ohne Dezimalpunkt in Python keinen Dezimalpunkt hat, d. h., wenn die Zahlen, mit denen zu rechnen sind, in der Zahlenmenge der Ganzen Zahlen liegen, liegt das Ergebnis auch dort.
Um das zu verhindern, reicht es, einer Zahl ein .0 anzuhängen. Um das dem Benutzer aber zu verschleiern, reicht es, folgende Zeile einzufügen:

Code: Alles auswählen

    zahl_2 /= 1.
Der Punkt ist dabei das wichtige, die zweite Zahl wird hier nämlich im voraus durch 1.0 dividiert.

Und nochwas:
Durch das try: kannst du auch ein korrektes Ergebnis bei Division durch 0 übergeben, statt eines Fehlers:

Code: Alles auswählen

elif choice == 4 :
    print ("Bitte stellen Sie nun Ihre Aufgabe")

    zahl_1 = int(input("Erste Zahl: "))
    zahl_2 = int(input("Zweite Zahl: "))
    try:
        result = zahl_1 / zahl_2
    except ZeroDivisionError:
        result = "Nicht definiert"
    print result
Ansonsten würde der Benutzer bei einer Aufgabe wie 20 / 0 folgendes kriegen:
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
0/0
ZeroDivisionError: integer division or modulo by zero
und das Programm wäre beendet.

So, als letztes vielleicht noch eine sauberere Lösung zum Neustart als ich oben genannt habe:

Code: Alles auswählen

def restart():
    """Asks the user if he wants to restart the calculator. """
    while True:
        reboot = raw_input(
            """Die Ausfuehrung des Programmes war erfolgreich. Wollen Sie es
neu starten? [J]a, [N]ein: """
            )
        reboot = reboot.lower()
        if reboot == 'j':
            print
            choice()
        elif reboot == 'n':
            sys.exit()
        else:
            print """Ihre Eingabe war leider nicht eindeutig. Bitte versuchen
Sie es erneut. """
Damit das dann aufgerufen wird, musst du die Funktion restart() am besten nach ganz oben schreiben und diese dann am Ende deiner Datei einfach mit restart() aufrufen. In meinem Beispiel ist es aber so, dass auch das Auswahlmenü in einer Funktion steckt. Des weiteren musst du bei meinem Beispiel noch über die Funktion restart() folgendes schreiben:

Code: Alles auswählen

import sys
Da das alles vielleicht ein bisschen umständlich klingt, habe ich mir auch mal einen Taschenrechner zusammen getüftelt. Einige Bildschirmausgaben und andere Strings sind gemäß PEP8 zweizeilig, deshalb werden sie mit drei Anführungszeichen eingeleitet.

Code: Alles auswählen

# A simple calculator
# Addition, subtraction, multiplication und exponentiation are
# supported
import sys

def addition_calc(num1, num2):
    """Addition of the two numbers num1 and num2. Function prints result."""
    result = num1 + num2
    print "Das Ergebnis der Rechnung lautet:", result

def subtraction_calc(num1, num2):
    """Subtraction of the two numbers num1 and num2. Function prints result."""
    result = num1 - num2
    print "Das Ergebnis der Rechnung lautet:", result

def multiplication_calc(num1, num2):
    """Multiplication of the two numbers num1 and num2. Function prints
result."""
    result = num1 * num2
    print "Das Ergebnis der Rechnung lautet:", result

def division_calc(num1, num2):
    """Division of the two numbers num1 and num2. Function prints result."""
    num2 /= 1.
    try:
        result = num1 / num2
    except ZeroDivisionError:
        result = "Nicht definiert"
    print "Das Ergebnis der Rechnung lautet:", result

def exponentiation_calc(num1, num2):
    """Exponentation of the two numbers num1 and num2. Function prints
result"""
    result = num1 ** num2
    print "Das Ergebnis der Rechnung lautet:", result

def addition_demand():
    """Function demands user to input the required numbers and calls the
function addition_calc()"""
    while True:
        try:
            num1 = int(
                raw_input(
                    "Geben Sie bitte den ersten Summanden ein: "
                    )
                )
            num2 = int(
                raw_input(
                    "Geben Sie bitte den zweiten Summanden ein: "
                    )
                )
            break
        except ValueError:
            print """Deine Eingabe war keine Zahl. Bitte versuche es noch
einmal."""
    print
    addition_calc(num1, num2)

def subtraction_demand():
    """Function demands user to input the required numbers and calls the
function subtraction_calc()"""
    while True:
        try:
            num1 = int(
                raw_input(
                    "Geben Sie bitte den Minuent ein: "
                    )
                )
            num2 = int(
                raw_input(
                    "Geben Sie bitte den Subtrahend ein: "
                    )
                )
            break
        except ValueError:
            print """Deine Eingabe war keine Zahl. Bitte versuche es noch
einmal."""
    print
    subtraction_calc(num1, num2)

def multiplication_demand():
    """Function demands user to input the required numbers and calls the
function multiplication_calc()"""
    while True:
        try:
            num1 = int(
                raw_input(
                    "Geben Sie bitte den ersten Faktor ein: "
                    )
                )
            num2 = int(
                raw_input(
                    "Geben Sie bitte den zweiten Faktor ein: "
                    )
                )
            break
        except ValueError:
            print """Deine Eingabe war keine Zahl. Bitte versuche es noch
einmal."""
    print
    multiplication_calc(num1, num2)

def division_demand():
    """Function demands user to input the required numbers and calls the
function division_calc()"""
    while True:
        try:
            num1 = int(
                raw_input(
                    "Geben Sie bitte den Divisor ein: "
                    )
                )
            num2 = int(
                raw_input(
                    "Geben Sie bitte den Divident ein: "
                    )
                )
            break
        except ValueError:
            print """Deine Eingabe war keine Zahl. Bitte versuche es noch
einmal."""
    print
    division_calc(num1, num2)

def exponentiation_demand():
    """Function demands user to input the required numbers and calls the
function division_calc()"""
    while True:
        try:
            num1 = int(
                raw_input(
                    "Geben Sie bitte die Basis ein: "
                    )
                )
            num2 = int(
                raw_input(
                    "Geben Sie bitte den Exponenten ein: "
                    )
                )
            break
        except ValueError:
            print """Deine Eingabe war keine Zahl. Bitte versuche es noch
einmal."""
    print
    exponentiation_calc(num1, num2)

def choice():
    """User decides the arithmetic operator. Function calls, depending on the
user's decision, the demand()-function. """
    print "[1] Addition"
    print "[2] Subtraktion"
    print "[3] Multiplikation"
    print "[4] Division"
    print "[5] Potenzierung"
    while True:
        try:
            arithmetic_op = int(
                raw_input(
                    "Bitte waehlen Sie eine Rechenoperation: "
                    )
                )
            break
        except ValueError:
            print "Ihre Eingabe war keine Zahl. Bitte versuchen Sie es erneut."

    if arithmetic_op == 1:
        addition_demand()
    elif arithmetic_op == 2:
        subtraction_demand()
    elif arithmetic_op == 3:
        multiplication_demand()
    elif arithmetic_op == 4:
        division_demand()
    elif arithmetic_op == 5:
        exponentiation_demand()
    else:
        print """Ihre Eingabe war nicht eindeutig. Bitte versuchen Sie es
erneut."""
        choice()

def restart():
    """Asks the user if he wants to restart the calculator. """
    while True:
        reboot = raw_input(
            """Die Ausfuehrung des Programmes war erfolgreich. Wollen Sie es
neu starten? [J]a, [N]ein: """
            )
        reboot = reboot.lower()
        if reboot == 'j':
            print
            choice()
        elif reboot == 'n':
            sys.exit()
        else:
            print """Ihre Eingabe war leider nicht eindeutig. Bitte versuchen
Sie es erneut. """
        

print "Herzlich Willkommen zum Taschenrechner!"
choice()
print
restart()
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Hui... da weiß man kaum, wo man anfangen soll zu kritisieren!

Unter Linux kannst Du mal folgendes probieren (Script-Name natürlich anzupassen):

Code: Alles auswählen

yes 7 | ./simple_calc.py
Da wirst Du nach wenigen Augenblicken folgendes präsentiert bekommen:

Code: Alles auswählen

...
  File "./simple_calc.py", line 181, in choice
    choice()
  File "./simple_calc.py", line 181, in choice
    choice()
  File "./simple_calc.py", line 181, in choice
    choice()
  File "./simple_calc.py", line 161, in choice
    "Bitte waehlen Sie eine Rechenoperation: "
RuntimeError: maximum recursion depth exceeded
Du rufst ziemlich unbemerkt choice() rekursiv auf am Ende der Auswahl. Das Menü-Konstrukt ist dabei wirklich ziemlich krude aufgebaut. Zum einen hast Du eine "while True"-Schleife, die an sich eine gute Idee ist, jedoch brichst Du sie nach der Eingabe einer Zahl ab; der Test danach, ob die Zahl im Wertebereich liegt ruft dann den Fehler hervor.
Desweiteren besteht bei Dir kein Zusammenhang zwischen möglicher Option, dessen Titel und dessen Überprüfung (Nummer). Wieso packst Du das nicht in ein Dictionary oder eine Liste? Damit könnte man zum einen den Text automatisieren und zum anderen das Testen vereinfachen. Zudem wäre das Erweitern wesentlich einfacher. Iirc hatten wir das aber schon weiter oben im Thread... BlackJack hatte das doch sehr schön dargestellt!

In der restart() Funktion ist übrigens auch eine Rekursion versteckt.

Desweiteren leidet der Code an vielen DRY-Verletzungen! Diese ganzen {{operation}}_demand()-Funktionen sind ja grauenhaft...

Auch das manuelle Aufrufen der Operationen sind ziemlich unnötig; BlackJack hatte auch hier auf das operator-Modul verwiesen.

Im Grunde reduziert sich das ganze doch auf eine nette Individualisierung der Parameter-Bennenung. Aber auch das könnte man einfach ein eine Funktion auslagern, die eine entsprechende Datenstruktur aus Bezeichnern enthält. Die Rückgaben könnten dann an die Berechnungsfunktion übergeben werden (wie BJ das auch schön gezeigt hatte).

Dabei würde ich auch eher diese Reihenfolge favourisieren:

Code: Alles auswählen

def calc(func, *operators):
    "hier findet eigentliche Berechnung statt"

def get_params(func_name, *param_names):
    "Hier Parameter abfragen, parsen, Syntaxprüfung etc + Rückgabe"

def main():
    # irgend wie noch Menü für Func Auswahl
    # bei passender Func
    ops = get_params()
    calc(func, ops)
Du hast hier das calc() immer in die Parameter-Abfrage-Funktionen gestellt. Macht keinen großen Unterschied, das Verfolgen des Ablaufs fällt in der gezeigten Variante aber leichter.

Zudem fehlt in Deiner Version auch der "if __name__ == '__main__'"-Hook.

Alles in allem: Kein guter Beispiel-Code - außer zur Demonstration, wie man es nicht machen sollte ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@ZEins: Ein ``x /= 1.0`` um `x` an eine Fliesskommazahl zu binden ist zwar eine witzige Idee, aber die dafür vorgesehene `float()`-Funktion zu verwenden, ist vielleicht doch etwas verständlicher. ;-)
Antworten