andie39‘s Fragen Thread

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.
Benutzeravatar
andie39
User
Beiträge: 152
Registriert: Dienstag 7. Dezember 2021, 16:32

So, ich habe nun die Funktion zum suchen eines Films in der Datenbank geschrieben und die halbwegs die Funktion einen Film als Verliehen oder Verfügbar zu markieren:
Hier die Funktion zur Suche:

Code: Alles auswählen

def find_movie():
    with open ("movies.csv", "r") as file:
        lines = file.readlines()
        eingabe = input("Welchen Film suchen Sie?")
        for element in lines:
            if eingabe == element.strip("\n"):
                print(f"{eingabe}, ist in der Datenbank vorhanden.")
                break
        
        else:
            print(f"{eingabe} ist in der Datenbank NICHT vorhanden.")
       
Und hier einen Film als verliehen und verfügbar zu markieren:

Code: Alles auswählen


def mark_lend():
    with open ("movies.csv", "r") as file:
        lines = file.readlines()
        movies_marked = {}
        eingabe = input("Welcher Film soll als verliehen markiert werden?")
        for element in lines:
            if eingabe == element.strip("\n"):
                movies_marked[element] = "Verliehen"
            else:
                movies_marked[element] = "Verfügbar"
 
 
Aber das ist erzeugt nur ein Dictionary welches den eingegebenen Film als verliehen und die anderen als verfügbar kennzeichnet.
Er müsste dann noch in die movies.csv schreiben und dort diese Informationen setzen und natürlich auch die, die noch als verliehen dort sind, dürfen nicht einfach überschrieben werden.

Je mehr ich mir das so ansehe und dazu google stelle ich fest:

So aufwendig sollte das in der Realität niemals sein.
das CSV Modul von Anfang an würde vieles erleichtern, wie auch hier ja schon geschrieben wurde.

Und auch _blackjack_ hat Recht:
Die Funktionen sollten einfacher gehalten werden.



Allerdings ging es mir ja auch darum, gelerntes zu probieren.
Nachdem Filme hinzufügen, Filme entfernen und Filme suchen im nachhinein nicht so ein Problem sind, da diese ja nur eine einfache Liste sind, wird es mit der Zusatz ob die verliehen oder verfügbar sind etwas schwieriger.

Abgesehen vom CSV Modul etc.

Wenn man es so programmieren würde wie ich es gerade versuche, ohne Module etc:

Wie würdet ihr es machen?
Die Funktion die,die Filme kennzeichnet so schreiben, dass diese ein dictionary erzeugt,
wie oben, aber erst noch prüft ob hier einige bereits den Wert "verliehen" haben und diese dann entsprechend überspringen?
Dieses dictonary dann in eine neue Datei schreiben die man aufrufen und prüfen kann?

Das wäre so mein Gedanke, wie seht ihr das?
Benutzeravatar
__blackjack__
User
Beiträge: 13077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@andie39: Du könntest eine extra Datei erstellen wo die verliehenen Filme entweder extra gespeichert werden, oder das Programm so schreiben, dass die verliehenen Filme sozusagen verschoben werden, also wenn Film X verliehen wird, dann aus der movies-Datei entfernen und zur lent-movies-Datei hinzufügen und wenn der Film zurück kommt, das ganze wieder umgekehrt.

Oder Du speicherst die Information zu jedem Film dazu, beispielsweise das Filme die da sind, als erstes Zeichen vor dem Titel ein "+" haben und alle die verliehen sind ein "-".

In beiden Fällen würde ich dann wieder dafür plädieren, dass es eine Lese- und eine Schreibfunktion gibt und diese beiden Funktionen die *einzigen* sind, die etwas von "+", "-", und "\n" wissen. Liefern und als Argument erwarten würden diese beiden Funktionen dann Listen aus Tupeln (Filmtitel, Wahrheitswert), wobei der Wahrheitswert, also `True` oder `False` aussagt ob der Film verfügbar oder verliehen ist. Wobei es auch gerne ein `collection.namedtuple()`-Typ sein darf, der diese beiden Informationen zusammenfasst.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
andie39
User
Beiträge: 152
Registriert: Dienstag 7. Dezember 2021, 16:32

Hmm….
gute Frage wie ich das am besten machen sollte.

Ich habe mir aber mal deine Beispiele hier genauer angesehen:

Code: Alles auswählen


def validate_movie(movie):
    if "\n" in movie:
        raise ValueError(f"illegal newline in {movie!r}")
    return movie


def load_movies(filename):
    with open(filename, "r", encoding="utf-8") as file:
        return [line.rstrip() for line in file]


def save_movies(filename, movies):
    with open(filename, "w", encoding="utf-8") as file:
        file.writelines(f"{validate_movie(movie)}\n" for movie in movies)


def add_movie(filename, movie):
    validate_movie(movie)
    
    movies = load_movies(filename)
    if movie in movies:
        return False

    movies.append(movie)
    save_movies(filename, movies)
    return True

Sieht sinnvoll aus, kleinere Funktionen werden in andere mit eingebaut so das man die auch nicht immer neu schreiben muss.

Sehr clever.

Aber ich habe ich eine Frage zu einer Funktion :


Load und safe öffnen und schreiben ja nur.
Load erstellt eine Liste die wird als movies später definiert und dort ein Film in die Liste hinzugefügt um dann die neue Liste Zeile für Zeile damit save dort eben die einzelnen Filme wieder in die Datei reinschreibt das macht soweit Sinn aber hier, dieser Teil der add Funktion:

Code: Alles auswählen


movies = load_movies(filename)
    if movie in movies:
        return False

    movies.append(movie)
    save_movies(filename, movies)
    return True

Ich weiss das man einen Rückgabewert entsprechend false oder true nach Bool definieren kann, aber was macht das genau?
Was bringt die Rückgabe false?
Lässt es das Programm dann hier stoppen, so dass die Funktion nicht weiter ausgeführt wird? Was hier ja das hinzufügen des Films und die Datei neu schreiben wäre?

Und wenn ja, wäre die Rückgabe true am Ende der Funktion dann nicht überflüssig da die Funkt dort sowieso endet?
Benutzeravatar
__blackjack__
User
Beiträge: 13077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@andie39: Die Funktion selbst macht mit dem Rückgabewert nichts, aber der Aufrufer kann daran feststellen ob der Aufruf geklappt hat, oder ob es den Film schon gab. In den Funktionen ist ja keine Benutzerinteraktion enthalten. Der Code der das aufruft, möchte dem Benutzer vielleicht gerne mitteilen ob das hinzufügen erfolgreich war oder nicht. Wenn einen das nicht interessiert, kann man das ignorieren.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
andie39
User
Beiträge: 152
Registriert: Dienstag 7. Dezember 2021, 16:32

__blackjack__ hat geschrieben: Montag 17. Januar 2022, 01:12 @andie39: Die Funktion selbst macht mit dem Rückgabewert nichts, aber der Aufrufer kann daran feststellen ob der Aufruf geklappt hat, oder ob es den Film schon gab. In den Funktionen ist ja keine Benutzerinteraktion enthalten. Der Code der das aufruft, möchte dem Benutzer vielleicht gerne mitteilen ob das hinzufügen erfolgreich war oder nicht. Wenn einen das nicht interessiert, kann man das ignorieren.
Ok, aber dann wäre doch ein print Befehl eher nötig, der mitteilt ob es den Film gibt oder nicht?
Du benutzt es ja auch bei der load_movies, aber das würde doch auch ohne gehen oder nicht?
Also so:

Code: Alles auswählen

def load_movies(filename):
    with open(filename, "r", encoding="utf-8") as file:
        [line.rstrip() for line in file]
       
Muss doch nicht extra das return hin?


Desweiteren bei der add_movie dann:

Code: Alles auswählen



def add_movie(filename, movie):
    validate_movie(movie)
    
    movies = load_movies(filename)
    if movie in movies:
        return False

    movies.append(movie)
    save_movies(filename, movies)
Würde jetzt nicht der Film so oder so hinzugefügt werden, auch wenn der schon verfügbar ist?
Denn movies.append(movie) ist ja nicht im if block untergebracht sondern würde doch nach der if Anweisung so oder so ausgeführt werden, da nicht eingerückt oder nicht?
Benutzeravatar
__blackjack__
User
Beiträge: 13077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@andie39: Doch `load_movies()` braucht ein ``return``, was sollte den sonst zurückgegeben werden? Ohne explizites ``return`` wird in dem ``with``-Block eine Liste erstellt, und die wird dann einfach verworfen, weil nichts damit gemacht wird. Und dann läuft die Funktion weiter hinter den ``with``-Block. Da steht nichts mehr, also ist der Ablauf der Funktion da zuende und es wird zum Aufrufer zurückgekehrt und implizit `None` zurückgegeben.

``return`` heisst zu deutsch sowohl „kehre zurück“ (zum Aufrufer) als auch „gib zurück“ (an den Aufrufer) und kehrt zum Aufrufer zurück. Nicht irgendwann sondern *sofort*. Wenn der Film in der Liste enthalten ist, wird ``return False`` ausgeführt, was die Funktion sofort an der Stelle beendet.

Es kann sein, dass trotzdem zwischen dem tatsächlichen zurückkehren, und bevor der Programmablauf beim Aufrufer weiter geht, noch etwas passiert was *in* der Funktion steht oder veranlasst wurde, nämlich wenn das ``return`` nicht nur die Funktion, sondern auch ``with``-Blöcke, oder ``try``-Blöcke mit einem ``finally``-Block verlässt. Ersteres ist in `load_movies()` der Fall wo das verlassen des ``with``-Blocks Code auslöst der die Datei schliesst. ``try``/``finally`` ist vielleicht ein Vorgriff auf Ausnahmebehandlung, wo ich jetzt nicht weiss ob Du das schon als Thema hattest.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
andie39
User
Beiträge: 152
Registriert: Dienstag 7. Dezember 2021, 16:32

Es wird doch etwas mit der Liste gemacht zumindest in der add_movies:

def load_movies(filename):
with open(filename, "r", encoding="utf-8") as file:
[line.rstrip() for line in file]

Hier wird ja eine Liste erstellt und diese liste bekommt doch in der add_movies gleich die Variable movies zugewiesen hier:

def add_movie(filename, movie):
validate_movie(movie)

movies = load_movies(filename)

——————

Ach return beendet auch eine Funktion?
Ich dachte das die nur etwas zurück gibt.

Beispiel man hat eine Berechnung laufen:

a +b- c = result
return(result)

Das dies dann eben zurückgegeben wird.

Hier aber wird die Liste ja so oder so erstellt. Das heißt return beendet immer die Funktion und lässt den Rest nicht weiterlaufen außer durch einen Zusatz wie try etc?
Benutzeravatar
__blackjack__
User
Beiträge: 13077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@andie39: In der `load_movies()` wird nichts mit der Liste gemacht. Insbesondere wird die nicht an den Aufrufer, also zum Beispiel `add_movie()` zurückgegeben. Das die den Rückgabewert von `load_movies()` an einen Namen bindet hat innerhalb der `load_movie()`-Funktion keinen Einfluss auf irgend etwas. Wenn `load_movies()`, beziehungsweise ganz allgemein eine Funktion nicht explizit etwas zurück gibt und der Programmfluss am Ende der Funktion ankommt, dann wird implizit der Wert `None` zurück gegeben. Du kannst Dir am Ende *jeder* Funktion (und Methode) ein unsichtbares ``return None`` vorstellen. Wenn das nicht so gelöst wäre, müsste die Sprache/Laufzeitumgebung irgendwie zwischen Funktionen/Methoden die etwas zurückgeben und welchen die das nicht tun unterscheiden, und das bei jedem Aufruf testen und gegebenenfalls eine Fehlermeldung/Ausnahme auslösen. Hätten die Python-Entwickler so machen können, haben sie aber nicht.

Und ja, ``return`` beendet, wenn es ausgeführt wird, die Funktion.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
andie39
User
Beiträge: 152
Registriert: Dienstag 7. Dezember 2021, 16:32

Danke.

Ok also wenn irgendwo retund in einer Funktion ausgeführt wird stoppt diese.
Das erklärt das.

Das mit dem return bei load_movies im Zusammenhang mit add_movies verstehe ich nicht…….
Doch jetzt schon das return gibt die Liste zurück.

Ich dachte nur weil:

[line.rstrip() for line in file]

Die eckigen Klammern erzeugen ja eine Liste.
Return gibt die zurück.

Ich dachte das auch ohne return die Funktion
aufgrund der letzten Zeile:
[line.rstrip() for line in file]

Eine Liste erzeugt und an die Funktion bindet.

Aber ja es ist ja wie bei meinem Beispiel einer berechnung bei der ja das result zurückgegeben werden soll.
Das resultat ist ja hier die Liste.
Benutzeravatar
andie39
User
Beiträge: 152
Registriert: Dienstag 7. Dezember 2021, 16:32

Ich habe hier in den letzten Tagen einiges gelernt auch Dinge die ich falsch angenommen hatte:

1. Die else Ausführung bei einer for/while Schleife und dahingehend im Zusammenhang mit break

2. Den return Befehl besser verstanden und das dieser eine Funktion beendet mit einigen try/except Ausnahmen.

3. Zukünftig die Arbeit mit bestehenden Modulen

4. Am wichtigsten aber wohl:
Funktionen so klein wie möglich halten und nur das rein was die wirklich machen sollen und dann weitere mit anderen Funktionen zusammen konstruieren.


Danke allen!!
Benutzeravatar
andie39
User
Beiträge: 152
Registriert: Dienstag 7. Dezember 2021, 16:32

Zwecks Unterscheidung von verliehen und verfügbaren Filmen habe ich mir folgende Lösung überlegt:

Ein Dictionary das zwei Keys kennt: Verliehen und verfügbar. Die Werte sind die Filme die dann in einer Liste diesen Keys zugeordnet werden.

Macht das Sinn?
Benutzeravatar
sparrow
User
Beiträge: 4187
Registriert: Freitag 17. April 2009, 10:28

Eigentlich ist das eine Eigenschaft, die ich beim Film erwarten würde. Verliehen oder nicht. Oder ein Status der nicht nur 2 Werte haben kann: Verliehen/Verloren/Aussortiert.
Benutzeravatar
andie39
User
Beiträge: 152
Registriert: Dienstag 7. Dezember 2021, 16:32

sparrow hat geschrieben: Mittwoch 19. Januar 2022, 06:17 Eigentlich ist das eine Eigenschaft, die ich beim Film erwarten würde. Verliehen oder nicht. Oder ein Status der nicht nur 2 Werte haben kann: Verliehen/Verloren/Aussortiert.

Eigenschaft? Also per Dictionary?
Benutzeravatar
sparrow
User
Beiträge: 4187
Registriert: Freitag 17. April 2009, 10:28

Versuch es doch?
Ich sehe nicht, wo ein dict weiterhelfen könnte. Kann der Film gleichzeitig verfügbar und verliehen sein? Oder eher nicht? Wenn nicht, warum braucht es dann zwei Eigentschaften und nicht nur eine, die entwder oder ist?
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

@andie39,

es hängt davon ab welche Daten du über die Filme speichern möchtest.
Ein Dictionary, dazu passt gut eine json-Datei, kann beliebig verschachtelte Daten aufnehmen und ist in seiner Struktur sehr flexibel.

Code: Alles auswählen

movies = {
    "Rambo": {
        "verfügbar": True,
        "Spielzeit": 120,
        "Hauptdarsteller": {
            "Vorname": "Sylvester",
            "Nachname": "Stallone"
        },
    },
    "Rambo 2": {
        "verfügbar": False,
        "Spielzeit": 121,
        "Hauptdarsteller": {
            "Vorname": "Sylvester",
            "Nachname": "Stallone"
        },
    }
}
Listen von Listen oder Tupeln können nur tabellarische Daten aufnehmen. Dazu passen csv-Dateien oder Excel-Tabellen.

Code: Alles auswählen

movies = [
    ("Rambo", True, 120, "Sylvester Stalone"),
    ("Rambo 2", False, 121, "Sylvester Stalone")
]
Dictionaries können in Teilen auch Listen enthalten.
Benutzeravatar
andie39
User
Beiträge: 152
Registriert: Dienstag 7. Dezember 2021, 16:32

Darum frage ich.
Jetzt sollen die ja nur verfügbar oder verliehen kennen.
Was ist denn die beste Lösung nach den Profis hier?
Benutzeravatar
andie39
User
Beiträge: 152
Registriert: Dienstag 7. Dezember 2021, 16:32

sparrow hat geschrieben: Mittwoch 19. Januar 2022, 06:17 Eigentlich ist das eine Eigenschaft, die ich beim Film erwarten würde. Verliehen oder nicht. Oder ein Status der nicht nur 2 Werte haben kann: Verliehen/Verloren/Aussortiert.
Du meinst Eigenschaft aus der Objektorientietung?
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

@andie39,

verfügbar / verliehen ist *ein* Attribut, so wie an / aus. Man hat ja auch keine Anschalter und separate Ausschalter für's Licht. Ein Schalter kann beide Zustände darstellen. So ist das auch bei dem Attribut "verfügbar" / "verliehen" das ist ein boolscher Wahrheitswert.

verfügbar == True -> kann ausgeliehen werden
verfügbar == False -> kann nicht ausgeliehen werden.

Attribut, Eigenschaft, Property ist hier im weiteren Sinne das gleiche und hat erstmal nichts mit Objektorientierung zu tun.
Erst wenn es an die technische Umsetzung geht, kann es sein, dass das Attribut "verfügbar" auch ein Attribut in einer Klasse ist. Es kann aber auch einer Spalte in einer csv-Tabelle oder einem Schlüssel in einem Dictionary entsprechen.

Aktuell hast du ja nur das Attribut "Name" und das Attribut "verliehen" .
Das kann dann also eine csv-Datei sein, in der jeder Film ein Zeile mit seinen Attributen belegt.
In der Spalte "Name" steht halt "Rambo" oder "Escaperoom" und in der Spalte "verliehen" steht entweder True oder False.
Benutzeravatar
andie39
User
Beiträge: 152
Registriert: Dienstag 7. Dezember 2021, 16:32

Das war meine Frage, weil ich gerade das neue Thema Klassen begonnen habe.

Ob das gemeint war oder eine einfachere Lösung
Benutzeravatar
andie39
User
Beiträge: 152
Registriert: Dienstag 7. Dezember 2021, 16:32

NEUE FRAGE

Aktuell bin ich dabei list comprehensions zu verstehen, grundsätzlich tue ich das.
Aber doch stolpere ich etwas wenn es komplexer wird auch im Hinblick der Schleifen, sprich genauer wenn zwei Schleifen zum Einsatz kommen.
Bei einer einzelnen ist das nicht das Problem.

Beispiel:

numbers_times_2 = [x*2 for x in numbers]

Code: Alles auswählen

numbers = [1,2,3,4,5,6]
numbers_times_2 = [x*2 for x in numbers]
Das das gleiche wie:

Code: Alles auswählen

numbers_times_2 = []
    for x in numbers:
        numbers_times_2.append(x*2)
Das verstehe ich auch.

Aber bei einem größeren Beispiel:

Siehe hier:
https://einfachpython.de/python-list-co ... erstellen/

Code: Alles auswählen


weekday_temperatures = [
{'day': 'Monday',    'date': '2019-07-15', 'temperature': 31},
{'day': 'Tuesday',   'date': '2019-07-16', 'temperature': 33},
{'day': 'Wednesday', 'date': '2019-07-17', 'temperature': 27},
{'day': 'Thursday',  'date': '2019-07-18', 'temperature': 25},
{'day': 'Friday',    'date': '2019-07-19', 'temperature': 30},
{'day': 'Saturday',  'date': '2019-07-20', 'temperature': 31},
{'day': 'Sunday',    'date': '2019-07-21', 'temperature': 29},
{'day': 'Monday',    'date': '2019-07-22', 'temperature': 25},
{'day': 'Tuesday',   'date': '2019-07-23', 'temperature': 31},
{'day': 'Wednesday', 'date': '2019-07-24', 'temperature': 26},
{'day': 'Thursday',  'date': '2019-07-25', 'temperature': 23},
{'day': 'Friday',    'date': '2019-07-26', 'temperature': 22},
{'day': 'Saturday',  'date': '2019-07-27', 'temperature': 23},
{'day': 'Sunday',    'date': '2019-07-28', 'temperature': 32}
]
hot_work_days = [(hot_day['date'], hot_day['temperature']) for hot_day in[workday for workday in weekday_temperatures if workday['day'] not in ['Saturday', 'Sunday']] if hot_day['temperature'] >= 30]


Ich verstehe hier folgendes:

hot_work_days = [(hot_day['date'], hot_day['temperature']) for hot_day in[workday for workday in weekday_temperatures if workday['day'] not in ['Saturday', 'Sunday']] if hot_day['temperature'] >= 30]
Es ist in eine ecke Klammer gesetzt weil die Variabel ja eine Liste sein soll.
(hot_day['date'], hot_day['temperature']) ist am Anfang und ja wenn man so will das, was in der Liste ausgegeben werden soll.
Es soll der Wert von date und temperatur ausgegeben werden Zeile für Zeile also für jede Zeile hot_day und später dann eben unter der Bedningung das die Temperatur größer oder gleich 30 ist:
if hot_day['temperature'] >= 30]
Auch wird nach dem Tag durchsucht und auch hier gibt es eine Bedingung.

Was mir hier nicht ganz klar ist, hot_day iterierung läuft ja auch über die Liste: weekday_temperatures.
Das wird aber nicht direkt so benannt sonder:
for hot_day in und dann kommt in einer eigenen Klammer/Liste die Suche nach dem Tag, diese Suche/Schleife verweißt ja erst explizit auf die weekday_temperatures.
Ist für mich sehr schwierig zu verstehen.
Und die alternative Form ist mir auch nicht klar wie die ausgeschrieben werden würde.

Wie kann man diese verschachtelten Listen genau verstehen?
Antworten