Funktion verstehen

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
scobbiedo
User
Beiträge: 8
Registriert: Montag 15. April 2019, 19:13

Hallo Zusammen
Ich bin bei einer Aufgabe auf eine Funktion gestossen, den ich nicht ganz verstehe..
Und zwar:

def __init__(self, datei)
self._data = ''
self._file = datei
_regex = re.compile(r"\w+,[0-9]+,[0-9]+\.[0- 9]+")
with open(datei, 'a+') as f:
for line in f:
if _regex.match(line):
self._data += line

Nun soll diese Funktion folgendes tun:
Es öffnen eine vorhandene Text Datei. Falls diese nicht vorhanden ist, wird eine neue erstellt. Die Datei soll eine Rangliste darstellen:

Paul, 35, 18.9
..

wobei mit 35 die Punkte und 18.9 die Zeit gemeint ist.

Nun: Was genau ist dieser regex Ausdruck?
Und was bedeutet diese 'a+'

Ich danke euch vielmals!
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

scobbiedo hat geschrieben: Montag 15. April 2019, 19:22 Nun: Was genau ist dieser regex Ausdruck?
Und was bedeutet diese 'a+'
Reguläre Ausdrücke: https://docs.python.org/3/library/re.html
open: https://docs.python.org/3/library/functions.html#open
scobbiedo
User
Beiträge: 8
Registriert: Montag 15. April 2019, 19:13

/me hat geschrieben: Montag 15. April 2019, 19:45
scobbiedo hat geschrieben: Montag 15. April 2019, 19:22 Nun: Was genau ist dieser regex Ausdruck?
Und was bedeutet diese 'a+'
Reguläre Ausdrücke: https://docs.python.org/3/library/re.html
open: https://docs.python.org/3/library/functions.html#open

Danke dir. Ich habe die Seite über reguläre Ausdrücke gesehen. Trotzdem bin ich ein bisschen unsicher, weshalb ich das brauche?
Und ich finde leider auch keine gute Beschreibung was zB das r"\w bedeutet?

Kann ich die Datei nicht einfach mit open öffnen?
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@scobbiedo: der Dateimodus `a+` ist eigentlich nie sinnvoll. Man will entweder eine Datei lesen, oder Zeilen an eine Datei anhängen, beides gleichzeitig führt nur zu Chaos. Der reguläre Ausdruck enthält zu viele Leerzeichen. Normalerweise will man Daten in Listen speichern, vor allem wenn man sie weiterverarbeiten will, will man die Teile des regulären Ausdrucks einzeln haben. `_regex` zeigt durch den Unterstrich an, dass man zwar an der Stelle eine Variable braucht, diese aber nicht benutzt; das ist hier offensichtlich falsch. Will man wirklich beliebigen Text nach der letzten Zahl erlauben?
scobbiedo
User
Beiträge: 8
Registriert: Montag 15. April 2019, 19:13

Danke für deine Nachricht.
Die Funktion soll einfach eine .txt Datei einlesen. Wenn sie nicht vorhanden ist, soll eine neue erstellt werden.
Falls sie vorhanden ist, dann befindet sich eine Rangliste drin mit
Name, Punkte, Zeit
str, int, float

Und ich verstehe halt nicht, was dieser regex Ausdruck genau macht und weshalb der nötig ist. Auch verstehe ich die anschliessende for Schleife nicht genau.
Muss das so kompliziert gemacht werden, oder gibt es einen anderen Weg?
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

Bisher machst Du noch gar nichts, also ist alles, was Du machst zu kompliziert. Eine Datei anzulegen, wenn man sie eigentlich nur lesen will, ist ein Fehler.

Also, was willst Du mit der Rangliste machen?
scobbiedo
User
Beiträge: 8
Registriert: Montag 15. April 2019, 19:13

Nein, ich möchte sie eben nicht nur lesen.. Meine Frag hier ist nur der erste Teil.. Wie man überhaupt erst die Datei einliest oder eben erstellt.

Anschliessend soll ich die Datei noch in ein Dictionary umwandeln, Werte hinzufügen und wieder löschen, sie sortieren etc..
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

Das Vorgehen ist immer, erster Schritt, Datei lesen und den Inhalt in eine passende Datenstruktur packen. Der String `self._data` ist keine passende Datenstruktur und das Erzeugen der Datei ist auch nicht sinnvoll. Wenn keine Datei existiert, ist einfach die Datenstruktur leer. Der reguläre Ausdruck könnte helfen, die Datenstruktur zu erzeugen, hier würde ich aber einfach mal , splitten, ist einfacher zu verstehen, als ein regulärer Ausdruck.
Zweiter Schritt wäre die Verarbeitung, also Werte hinzufügen, löschen, etc.
Dritter Schritt ist das Schreiben der Daten in eine Datei. Hier würde man dann auch die Datei erzeugen, wenn sie noch nicht existiert.
Benutzeravatar
__blackjack__
User
Beiträge: 13103
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@scobbiedo: Es wurde ja schon gesagt das man sie nicht erstellt. Das macht keinen Sinn. Lies sie einfach nur ein und behandle den Fall, das sie nicht existiert so als wäre sie leer. Das erstellen kann man machen wenn die Daten gespeichert werden.

Was den regulären Ausdruck angeht: Wo genau hast Du denn dabei ein Problem? Du hast nachgelesen was die `match()`-Methode macht? Und die Dokumentation und das Howto zu regulären Ausdrücken in der Python-Dokumentation?

So ganz verstehe ich den Sinn hier aber auch nicht, denn normalerweise würde man die Datei lesen und erwarten das alle Zeilen dem erwarteten Muster entsprechen, und falls nicht eine Ausnahme auslösen, und nicht einfach Zeilen ignorieren, die nicht dem Muster entsprechen.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
scobbiedo
User
Beiträge: 8
Registriert: Montag 15. April 2019, 19:13

Sirius3 hat geschrieben: Montag 15. April 2019, 21:54 Das Vorgehen ist immer, erster Schritt, Datei lesen und den Inhalt in eine passende Datenstruktur packen. Der String `self._data` ist keine passende Datenstruktur und das Erzeugen der Datei ist auch nicht sinnvoll. Wenn keine Datei existiert, ist einfach die Datenstruktur leer. Der reguläre Ausdruck könnte helfen, die Datenstruktur zu erzeugen, hier würde ich aber einfach mal , splitten, ist einfacher zu verstehen, als ein regulärer Ausdruck.
Zweiter Schritt wäre die Verarbeitung, also Werte hinzufügen, löschen, etc.
Dritter Schritt ist das Schreiben der Daten in eine Datei. Hier würde man dann auch die Datei erzeugen, wenn sie noch nicht existiert.
Die Methoden sind eben klar aufgeteilt.
Die init Methode soll die angegebene Textdatei (encoding=’utf-8’) einlesen und die Daten in eine nicht-öffentliche Instanzvariable abspeichern, wobei leere oder unguültige Zeilen ignoriert werden. Ebenso soll sie eine neue leere Datei erstellen, falls diese noch nicht existiert.

Hinzufügen etc kommen dann in seperaten Methoden.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

die Daten sollten aber nicht als einfacher String abgelegt werden. Und das Erzeugen einer Datei ist an der Stelle halt falsch und bleibt falsch, auch wenn Du es noch öfter wiederholst.
scobbiedo
User
Beiträge: 8
Registriert: Montag 15. April 2019, 19:13

Es tut mir ja wirklich Leid, ich bin sehr neu in Python und ich wollte hier um Hilfe fragen. Aber wenn du mir einfach immer sagst, was falsch ist, dann bringt mich das nicht viel weiter..Aber danke trotzdem für deine Mühe zu antworten.
Benutzeravatar
__blackjack__
User
Beiträge: 13103
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@scobbiedo: Wenn die Textdatei UTF-8-kodiert sein soll, muss man das bei `open()` auch angeben. Und es sollte Dich schon weiterbringen wenn Dir gesagt wird was falsch ist, denn dann kannst Du das sein lassen und es richtig machen.

Warum soll die `__init__()` die Datei ohne Inhalt anlegen? Das hat keinen Mehrwert, macht das Programm aber komplizierter und ”komisch”.

Und warum sollen leere und falsche Zeilen ignoriert werden? Damit verdeckt man Fehler, das ist keine gute Idee.

Den Dateiinhalt ohne fehlerhafte Zeilen als Zeichenkette an ein Attribut zu binden macht keinen Sinn wenn das gar nicht die Form ist in der man die Daten zur Weiterverarbeitung benötigt. Das wird nur dazu führen, dass man am Ende die Daten redundant in mehreren Formaten im gleichen Objekt hält, oder immer zwischen diesem Format und dem in dem man das *eigentlich* haben möchte, hin und her wandeln muss. Beides nicht effizient und mindestens die redundante Variante ist unnötig fehleranfällig.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
scobbiedo
User
Beiträge: 8
Registriert: Montag 15. April 2019, 19:13

Danke _blackjack_.
Ich kann verstehen, wenn es sich für dich seltsam anhört. Leider ist das aber die Aufgabenstellung und ich muss es tatsächlich so machen. (leere Datei anlegen, Zeichen ignorieren etc das sind Vorgaben)
Deshalb verwirrt es mich ja auch ein bisschen.
Benutzeravatar
__blackjack__
User
Beiträge: 13103
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@scobbiedo: Dann würde ich aber entweder den regulären Ausdruck auch gleich verwenden um an die einzelnen Werte zu kommen, oder aber ohne regulären Ausdruck arbeiten, wie das ja bereits beschrieben wurde, und entsprechend auf Ausnahmen beim aufteilen und umwandeln reagieren. Und was immer Du machst, schreib es selbst, und übernimm keine Lösungen die Du nicht verstehst.

Ich würde auch wenigstens eine Warnung bei falschen Zeilen ausgeben. Mindestens mit `print()`, besser vielleicht mit Hilfe des `logging`-Moduls.

Beim anlegen der Datei würde ich nicht auf kryptische, eigentlich nicht verwendete Dateimodi setzten, sondern auf die entsprechende Ausnahme reagieren wenn versucht wird eine nicht-existierende Datei zu öffnen. Und ich würde wohl auch als Kommentar meine Meinung zu dieser unsinnigen Anforderung im Code hinterlassen. In deutlichen Worten. :-)
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

Wie lauten denn die genauen Anforderungen? Ist gefordert, das mit regulären Ausdrücken zu implementieren?

Mein Vorgehen wäre:
Datei zum Lesen öffnen und zeilenweise am Komma splitten und die Spalten 2 und 3 in Zahlen umwandeln. Wenn dabei etwas schief geht, die Exception abfangen und ausgeben, dass es eine nicht korrekte Zeile gab, und dann weiter machen.
Falls das Öffnen der Datei nicht klappt, versuchen, die Datei anzulegen.
scobbiedo
User
Beiträge: 8
Registriert: Montag 15. April 2019, 19:13

Nein, das mit regulären Ausdrücken gearbeitet wird ist nicht verlangt. Der Autor der Lösung fand das wohl praktisch..
Gefordert werden nur die 3 obengennanten Sachen:

-Datei (.txt File) einlesen
-leere und ungültige Zeilen ignoriere
-neue Datei erstellen falls sie noch nicht existiert

Also dann zB etwa so:
def _init_(self, datei)
self._datei= datei
datei.split(",")
?
Benutzeravatar
sparrow
User
Beiträge: 4193
Registriert: Freitag 17. April 2009, 10:28

Muss das ganze Objektorientiert gelöst werden?
Das ist in dem Fall ja nicht nötig. Das Ergebnis lässt sich mit 2 oder 3 Funktionen erreichen, ohne diese in eine Klasse zwingen zu müssen. Wir sind ja nicht bei Java, wo das erzwungen ist.

Dein "in etwa so" kannst du ja im Interpreter selbst ausprobieren. Das wird so nicht funktionieren.
Sirius3 hat dir doch einen Bauplan an die Hand gegeben, wie der Ablauf sein muss. Bau ihn doch einfach nach und schau, an welcher Stelle du nicht weiter kommst.
Benutzeravatar
__blackjack__
User
Beiträge: 13103
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Der Name `datei` ist übrigens falsch, weil es sich bei diesem Objekt gar nicht um eine Datei handelt, sondern um einen Datei*namen*. Korrekte, sinnvolle Namengebung ist sehr wichtig beim Programmieren.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten