Seite 1 von 1

Code verstehen - sqlite3

Verfasst: Freitag 19. April 2019, 16:55
von Devanther

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.

Re: Code verstehen - sqlite3

Verfasst: Freitag 19. April 2019, 17:29
von __blackjack__
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.

Re: Code verstehen - sqlite3

Verfasst: Freitag 19. April 2019, 17:50
von Sirius3
@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.

Re: Code verstehen - sqlite3

Verfasst: Freitag 19. April 2019, 19:10
von ThomasL
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.