Bank Projekt - Need help!

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
Mr.White
User
Beiträge: 46
Registriert: Samstag 7. März 2015, 20:03

Hey Leute,

Ich habe mir weitgehend alles selber beigebracht
was Python programmieren angeht. Nach längeren
suchen ist mir die Idee gekommen, mal so ein kleines System
zu schreiben, welches funktioniert wie eine Bank.


Problem:

Die Konten müssen irgendwo gespeichert und abgerufen werden.
So weit bin ich aber noch nicht mit dem lernen..
Es soll auch erst eine Transaktion durchgeführt werden können,
wenn mindestens 2 Konten bestehen...

Könnt ihr mir da irgendwie helfen ?

Hier mein Code:
PS: Ist ein wenig durcheinander...

Code: Alles auswählen


import random
import time

class Konto:
    def __init__(self):
        passwrd = random.randint(1,99999)
        idf = random.randint(1,99999)
        self.stnd = 500
        self.ID = idf
        self.PW = passwrd

    def kLogin(self):
        print("Gib bitte deine ID ein:")
        putID = int(input())
        if putID == self.ID:
            print("Konto existiert. Nun das Passwort:")
            putPW = int(input())
            if putPW == self.PW:
                print("Du bist eingeloggt.")
                kaction.kInfo()
                time.sleep(1.0)
                kaction.kother()
            elif putPW != self.PW:
                print("")
            else:
                print("")
        elif putID != self.ID:
            print("Falsche eingaben!")
        else:
            print("Falsche eingaben!")
                    
    def kother(self):
        print("Möchtest du eine Aktion ausführen ?:")
        decis = str(input())
        if decis == "Ja":
            print("Gut. Mögliche aktionen:")
            print()
            print("Überweisen")
            print("- /")
            print("- /")
            choose = str(input())
            if choose == "Überweisen":
                kaction.mTransfer()
            else:
                print(decis, "existiert nicht..")
                pass
        elif decis == "Nein":
            print("Dann nicht...")
            pass
        else:
            print("Falsche eingabe..")
    def ausgabe(self):
        print("ID:", self.ID)
        print("PW:", self.PW)

    def kInfo(self):
        print("Kontostand:")
        print(self.stnd)

    def mTransfer(self):
        print("Wird noch implementiert...")
        
                
kaction = Konto()
frage1 = 0

while frage1 == 0:
    print("Besitzt du bereits ein Konto ?:")
    decis = str(input())
    if decis == "Ja":
        print("Du wirst zum Login weitergeleitet...")
        time.sleep(9.0)
        print("Funktion wird noch implementiert!")
        frage1 = 1
        #Login
    elif decis == "Nein":
        print("Möchstest du eins erstellen ?:")
        decis = str(input())
        if decis == "Ja":
            print("Erstellt.")
            kaction.ausgabe()
            print()
            print("Einloggen?:")
            decis = str(input())
            if decis == "Ja":
                kaction.kLogin()
            elif decis == "Nein":
                print("Bis dann.")
                pass
            else:
                print("Flasche!!")
                frage1 == 0
        elif decis == "Nein":
            print("Also möchtest du nichts..ciao!")
            pass
        frage1 = 1
    else:
        print("Falsche eingaben, versuche es erneut..")
        time.sleep(0.5)
        frage1 == 0

Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Oha :shock: "Ein wenig" durcheinander ist eigentlich schon ein Euphemismus. Sorry, ich will Dich nicht demotivieren, aber das ist so viel Code, der sowohl vom Design als auch vom Erscheinungsbild schlecht ist, dass es sich nicht lohnt, damit weiter zu arbeiten!

Ich würde Dir raten, OOP erst einmal zu vergessen und das ganze mittels Funktionen und elementaren Datenstrukturen anzugehen, wie eben Dictionaries und Listen. Deine Klasse ist im aktuellen Zustand ziemlich sinnlos, da die quasi keinen inneren Zustand hat. Es werden lediglich Attribute angelegt, die sich aber nicht ändern über die Zeit. Die Namensgebung ist komplett missraten (wozu das ``k``-Präfix?), Du "missbrauchst" Integerwerte für Schleifenbedingungen (Python kennt ``True`` und ``False`` als Literale für den booleschen Typen!) und am allerschlimmsten: Du vermischst Logik und Ein- und Ausgaben munter miteinander.

Es mag hart klingen, aber: Das ist so nicht wirklich zu retten!

Fang einfach mal mit einer guten Datenstruktur an und schreib Funktionen, die diese manipulieren, anhand dieser etwas verifizieren (Login z.B.) und diese auch ausgeben können. Ich vermute mal, dass Du mit Dictionaries und Listen und deren Methoden noch gar nicht wirklich vertraut bist. Das ist aber ein elementares Thema und wichtig für alles weitere - auch für OOP später!

Versuche Dich an PEP8 zu halten und versuche Eingaben von Logik zu trennen, wo beides nicht zusammen gehört.

Schreib Funktionen so, dass Du ihnen Parameter übergeben kannst und diese Rückgabewerte liefern. Damit kannst Du sie universelller einsetzen. Außerdem sollte eine Funktion immer nur *eine* Aufgabe erfüllen. Also z.B. könnte es eine Funktion geben, die ein leeres Konto anlegt. Diese wsollte *nicht* nach dem Kontoinhaber fragen o.ä., sondern diesen als Parameter übergeben bekommen. Für das Erfragen des Kontoinhabers schreibe entsprechend eine eigene Funktion, die Dir den Namen oder die Struktur zurückgibt.

Wenn Du so vorgehst, also in kleinen Schritten, kommst Du schneller zu etwas nutz- und erweiterbaren! :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

Sqlite und ein wenig SQL ist in diesem Kontext sicher recht lehrreich. Und bitte trenne ein wenig mehr Logik von UI.
Und input liefert stets einen String zurück, dahin muss man nicht konvertieren. Pass bitte nur wenn da vorher noch nichts stehts und man einen Platzhalter braucht. Und Zuweisungen die nur den Zweck haben irgendwas temporär einen Namen zu geben sind ziemlich sinnfrei wie bei passwrd in __init__.
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
BlackJack

@Mr.White: Als erstes mal solltest Du die Geschäftslogik von der Benutzerinzeraktion trennen. `Konto`-Objekte sollten weder den Benutzer etwas fragen noch etwas mit `print()` ausgeben.

Dann sind die Namen teilweise sehr schlecht. Hast Du keine Umlaute auf Deiner Tastatur? Was sollen so Sachen wie `passwrd` oder `stnd`? `decis`? Und diese `k`-Präfixe bei einigen Methoden? Und bei der Gross-/Kleinschreibung könnte man sich auch an den Style Guide for Python Code halten.

Auch sollte man keine Namen durchnummerieren. Das ist so gut wie immer ein Zeichen dass man zu faul war sich richtige Namen auszudenken oder man möchte eigentlich eine Datenstruktur verwenden statt einzelner Namen. Oft ist das eine Liste.

Normalerweise haben Konten kein Passwort. Der *Nutzer* muss sich irgendwie Authentifizieren, zum Beispiel mit einer Bankkarte + PIN, aber das sind Daten die nicht beim Konto hinterlegt sind.

Eine zufällige Kontonummer birgt die Gefahr das am Ende mehr als ein Konto die selbe Nummer hat, ist also ein Programmfehler.

Das Hauptprogramm sollte auch in einer Funktion stecken. Auf Modulebene gehört nur Code der Konstanten, Funktionen, und Klassen definiert.
Mr.White
User
Beiträge: 46
Registriert: Samstag 7. März 2015, 20:03

Toll. Und wo hat mir das jetzt geholfen ??


Und was meint ihr wie ich am besten das zeug lernen soll...
Ich habe das ganze mit einem Kumpel gelernt der (anscheind ja nicht)
Python beherrscht.

So wurde mir das gezeigt, und so hab ich es angewendet...
Motivation habe ich jetzt auch nicht wirklich mehr.

Weil:

- Ich nicht(mehr) weiß wie ich es umsetzen soll.
- Wie OOP RICHTIG funktioniert.
- Wann und wieso ich irgendwas machen muss..

Ohne OOP sieht das Programm noch komischer aus..
BlackJack

@Mr.White: Du weisst jetzt, dass das Programm so nicht gut war, das man vernünftige Namen verwenden sollte, dass es einen Style Guide gibt, das man Benutzerinteraktion und Geschäftslogik nicht mischen sollte, Fehler die im Programm sind, und Du hast einen Ansatz beschrieben bekommen das erst einmal ohne eigene Klasse mit Funktionen umzusetzen. Also eigentlich eine Menge Sachen die man direkt mal umsetzen könnte.

Wie sollte man denn sonst helfen bei einem Quelltext der nicht mehr wirklich zu retten ist, weil das letztendlich keine kleinen Änderungen erfordert, beziehungsweise die kleinen Änderungen in Summe auf einen komplett neu geschriebenen Ansatz hinauslaufen würden.
Mr.White
User
Beiträge: 46
Registriert: Samstag 7. März 2015, 20:03

Ja ich weiß das es nicht GUT war, ich weiß, dass es den GUIDE gibt, und ich weiß, dass ich Logik und Grafik+Interaktion
nicht mischen soll.

Aber ich weiß nicht wie ich Logik und Grafik+Interaktion trenne...
Nie gelernt. Nie Probiert.

Ich habe es nur gemischt gelernt und weiß jetzt auch nicht wie
ich es änder.


Das Programm hab ich gelöscht und den Rest der so aufgebaut ist auch.
Gut. Alles was NICHT GUT ist existiert nicht mehr und ich brauche
nun einen Ansatz wo ich anfange. Ich weiß aber
zum verrecken nicht wie ich die GRAFIK + AUSGABEN etc. erst später einfüge!....
BlackJack

@Mr.White: Naja, das zu mischen bedeutet das Ein- und Ausgaben mit Code vermischt wird der den Zustand von den Daten verändert. Das zu trennen bedeutet es einfach nicht zu vermischen. In den Klassen zur Geschäftslogik einfach weder `print()` noch `input()` benutzen wäre der erste Schritt. Man muss Funktionen schreiben können die die Geschäftslogik testet ohne das der Benutzer etwas eingibt oder lesen muss. Wenn man das kann/macht, dann ist die Trennung okay.

Du musst Dir überlegen was für Datenstrukturen/Datentypen Du benötigst und welche Operationen darauf/damit durchgeführt werden. Und die dann ohne Code zur Benutzerinteraktion implementieren. Danach kann man dann den Code schreiben der mit dem Benutzer kommuniziert und mit den Datenstrukturen/Objekten dann arbeitet.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Wenn du es nie probiert hast, warum tust du das dann nicht?
Ich verstehe, dass das nicht ganz einfach und auch nicht ganz intuitiv verstaendlich ist. Aber das ist das wichtigste Problem hier auch gerade im Bezug auf dein Problem mit mehreren Konten.

Logik und Interaktion sollst du nicht mischen, aber offensichtlich muessen die beiden Sachen zusammenkommen. Gebraeuchlich ist das Model-View-Controller Pattern, nachdem du hier drei getrennte Entitaeten hast. Das Model stellt die Logik dar (hier die Bank(en) und Konten), View die Interaktion und der Controller kuemmert sich um das Zusammenspiel.
Das ist fuer das Problem hier vielleicht etwas ueberdimensioniert, aber man findet hierzu jede Menge Literatur.
Mr.White
User
Beiträge: 46
Registriert: Samstag 7. März 2015, 20:03

Ich fange am besten von 0 an..

sprich bei print("Hello world")

bis

OOP...

sonst komm ich hier gar nicht mehr klar.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Code wegwerfen und neu anfangen ist eine gute Idee. Das wirst du mit Sicherheit noch öfter machen, das ist zu Beginn vollkommen normal. Zu der Trennung von Logik und Ein-/Ausgabe mal ein ganz konkretes Beispiel.

Dein Ablauf sieht im Moment so aus:

Code: Alles auswählen

def verdoppeln():
    print int(raw_input("Bitte Zahl eingaben:")) * 2
Wenn du eine Zahl verdoppeln willst, dann wird immer der Benutzer nach einer Eingabe gefragt und das Ergebnis ausgegeben. Schöner geht es so:

Code: Alles auswählen

def verdoppeln(zahl):
    return 2*zahl

zahl = int(raw_input("Bitte Zahl eingaben:"))
print verdoppeln(zahl)
So kannst du die Funktion zum verdoppeln an anderer Stelle wiederverwenden. Zum Beispiel so:

Code: Alles auswählen

def vervierfachen(zahl):
    return verdoppeln(verdoppeln(zahl))
Hättest du Ein- und Ausgabe darin, dann ginge das nicht.

Und eine kleine Anmerkung noch zu deinen Texten: Bitte füge doch nicht überall Zeilenumbrüche ein, wo keine hingehören. Jeder Browser, bzw. Benutzer kann das selbst entscheiden, wie der Text bei sich dargestellt wird. Dein "Layout" nutzt nicht den Platz auf einem großen Monitor und auf kleinen Bildschirmen ist er total unleserlich.
Das Leben ist wie ein Tennisball.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

@EyDu: Sehr schönes, klares, einfaches und leicht verständliches Beispiel! :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Antworten