Code verstehen - sqlite3

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
Devanther
User
Beiträge: 13
Registriert: Samstag 23. März 2019, 21:45

Code: Alles auswählen

import sqlite3

db = sqlite3.connect("accounts.sqlite")
db.execute("CREATE TABLE IF NOT EXISTS accounts (name TEXT PRIMARY KEY NOT NULL, balance INTEGER NOT NULL)")
db.execute("CREATE TABLE IF NOT EXISTS transactions (time TIMESTAMP NOT NULL,"
           " account TEXT NOT NULL, amount INTEGER NOT NULL, PRIMARY KEY (time, account))")


class Account(object):

    def __init__(self, name: str, opening_balance: int = 0):
        cursor = db.execute("SELECT name, balance FROM accounts WHERE (name = ?)", (name,))
        row = cursor.fetchone()

        if row:
            self.name, self._balance = row
            print("Retrieved record for {}. ".format(self.name), end='')
        else:
            self.name = name
            self._balance = opening_balance
            cursor.execute("INSERT INTO accounts VALUES(?, ?)", (name, opening_balance))
            cursor.connection.commit()
            print("Account created for {}. ".format(self.name), end='')
        self.show_balance()

    def deposit(self, amount: int) -> float:
        if amount > 0.0:
            self._balance += amount
            print("{:.2f} deposited".format(amount / 100))
        return self._balance / 100

    def withdraw(self, amount: int) -> float:
        if 0 < amount <= self._balance:
            self._balance -= amount
            print("{:.2f} withdrawn".format(amount / 100))
            return amount / 100
        else:
            print("The amount must be greater than zero and no more than your account balance")
            return 0.0

    def show_balance(self):
        print("Balance on account {} is {:.2f}".format(self.name, self._balance / 100))

if __name__ == '__main__':
    john = Account("John")
    john.deposit(1010)
    john.deposit(10)
    john.deposit(10)
    john.withdraw(30)
    john.withdraw(0)
    john.show_balance()

    terry = Account("Terry")
    graham = Account("Graham", 9000)
    eric = Account("Eric", 7000)

    db.close()
Hallo,
ich verstehe leider nicht alles.

print("Retrieved record for {}. ".format(self.name), end='') ---------------------- was bedeutet das end='') .....?

def deposit(self, amount: int) -> float: ----------------- was wird da gemacht?

if __name__ == '__main__': -------------- was bedeutet diese Zeile? Was wird da gemacht?

row = cursor.fetchone() ------ was heisst das?

cursor.connection.commit() ----- was heisst das?



Ich habe erst Java gelernt und bin grade dabei Python zu lernen.
Irgendwie finde ich Java zwar umständlicher aber logischer und einfacher zu verstehen -.-

Wäre gut, wenn sich jemand paar Minuten Zeit nehmen würde.
Benutzeravatar
__blackjack__
User
Beiträge: 13080
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Devanther: Die Erklärung zum `end`-Argument in der Python-Dokumentation war nicht verständlich? Wenn Du das einfach mal mit und ohne in einer Python-Shell und vielleicht auch mal mit einem anderen Wert als der leeren Zeichenkette ausprobierst, wird das nicht klar?

Was verstehst Du am ``def deposit(…`` nicht? Da wird eine Methode definiert. Warum hast Du Dir gerade die Definition für die Frage heraus gesucht, und keine der anderen Methoden?

Was ist an `fetchone()` unverständlich? Auch die Methode ist dokumentiert. Und das wird doch auch aus dem Zusammenhang relativ deutlich.

Und auch das ``cursor.connection.commit()`` sollte sich mit der Dokumentation beantworten lassen. Wobei das ”falsch” ist – `Cursor` haben im allgemeinen laut DB API V2 kein `connection` – das ist eine Besonderheit vom `sqlite3`-Modul. Und es ist auch unsinnig darüber auf die Verbindung zuzugreifen, weil das `Cursor`-Objekt ja in der gleichen Methode von der Verbindung kommt. Wobei auch das wieder nicht API-konform ist: Die Verbindung hat eigentlich keine `execute()`-Methode. Wieder ein `sqlite3`-Sonderweg.

Insgesamt ist das mit der Datenbank falsch gelöst. Das fängt damit an, das beim einfachen Importieren des Moduls die Datenbankverbindung erstellt und gegebenfalls eine Datei angelegt wird, ob man das will oder nicht. Und so etwas will man nicht. Module sollten seiteneffektfrei importiert werden können.

Dazu ist dann auch das ``if __name__ == …:`` da. `__name__` hat beim importieren den Namen des Moduls als Wert. Nur wenn man das Modul als Programm ausführt, ist daran der Wert '__main__' gebunden.

Das was in dem Zweig steht, sollte aber in einer Funktion stehen, denn so wie es jetzt ist, werden Variablen auf Modulebene erstellt, die dort nicht hingehören.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Devanther: die API ist reichlich verwirrend.
Beim Erstellen von einer Account-Instanz wird mal `opening_balance` verwendet (falls der Name noch nicht in der Datenbank ist) oder einfach ignoriert.
`deposit` und `withdraw` erwarten einen Betrag in Cent, geben dann aber Euros als Rückgabewert zurück. Solche Unstimmigkeiten führen nur zu einer Unmenge an Benutzungsfehlern.
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Devanther hat geschrieben: Freitag 19. April 2019, 16:55 def deposit(self, amount: int) -> float: ----------------- was wird da gemacht?
Das nennt sich Type Annotations
https://docs.python.org/3/library/typing.html
https://www.python.org/dev/peps/pep-0484/
Kann man mögen, muss man aber nicht.
Erfüllen zur Zeit auch noch keinen tieferen Sinn oder Zweck.
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Antworten