Zeilen in einer Datei löschen über List-Comprehension
@sfx2k: Hier macht das `set` nun aber wieder keinen Sinn mehr. Da wäre eine Liste angebrachter weil das eine einfacherere Datenstruktur ist und Du von der Funktionalität vom `set` nichts verwendest.
Noch eine Variante das Ganze aufzuteilen. Eine Funktion zum Lesen, eine die eine einzelne Zeile prüft, und eine zum Schreiben des Ergebnis, und dann noch eine Hauptfunktion welche die drei Teile kombiniert:
Code: Alles auswählen
#!/usr/bin/env python
import re
from itertools import ifilterfalse
def iter_lines(filename):
with open(filename, 'r') as lines:
for line in lines:
yield line
def create_line_test(words):
return re.compile(
r'\b({0})\b'.format('|'.join(re.escape(word) for word in words)),
re.IGNORECASE
).search
def save_lines(filename, lines):
with open(filename, 'w') as out_file:
out_file.writelines(lines)
def main():
to_delete = ['ich', 'du', 'er', 'sie', 'es']
save_lines(
'test2.txt',
ifilterfalse(create_line_test(to_delete), iter_lines('test.txt'))
)
if __name__ == '__main__':
main()
Ha, das gefällt mir ausgezeichnet. Besonders die Möglichkeit, automatisch escapen zu lassenSirius3 hat geschrieben:Code: Alles auswählen
def some_filter(line, args): return not re.search(r'\b({})\b'.format('|'.join(map(re.escape, args))), line. re.I)
AhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhBlackJack hat geschrieben:@sfx2k: Hier macht das `set` nun aber wieder keinen Sinn mehr. Da wäre eine Liste angebrachter weil das eine einfacherere Datenstruktur ist und Du von der Funktionalität vom `set` nichts verwendest.
Okay, dann erkläre mir doch bitte, warum drei Posts vorher laut nezzcarth noch ein Set besser geeignet war als eine Liste, da ich deren Funktionalitäten gar nicht benötige, und jetzt genau andersrum?
Bezüglich Deines Quelltextes:
In Delphi hätte ich alles einzeln gemacht. Diese vielen verschachtelten Aufrufe - da muss ich erstmal mit klarkommen.
Besonders das ifilterfalse ist mir noch nicht ganz klar. Naja - mal das Doc dazu lesen
Sirius3 benutzt zum Zusammensetzen des Regulären Ausdrucks die map() Funktion, Du eine for-Schleife.
Gibt es da für diesen Fall signifikante Unterschiede? Oder ist das einfach nur Geschmackssache?
Und dann noch eine grundlegende Frage, auf die ich aber keine Antwort finden konnte:
Muss ich, wenn ein File in einer with-Anweisung geöffnet wird, dieses nicht auch wieder schließen?
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Weil Du da noch *ohne* reguläre Ausdrücke geprüft hast, ob ein Wort in einer *Menge* vorkommt. Du hattest eine Liste genommen, die beim ``in`` Operator jedes Mal schlimmsten Falls komplett durchlaufen werden muss (das beschreibt man auch mit O(n)). Bei einer Menge kann der ``in`` Operator in *konstanter* Zeit (O(1)) ermitteln, ob ein Element in einer Liste ist.sfx2k hat geschrieben: Ahhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
Okay, dann erkläre mir doch bitte, warum drei Posts vorher laut nezzcarth noch ein Set besser geeignet war als eine Liste, da ich deren Funktionalitäten gar nicht benötige, und jetzt genau andersrum?
Das kann man in einer Python-Shell (hier iPython) leicht nachprüfen:
Code: Alles auswählen
In [1]: values = list(range(10000000))
In [3]: some_value = 9999999
In [4]: timeit some_value in values
1 loops, best of 3: 305 ms per loop
In [5]: values = set(range(10000000))
In [6]: timeit some_value in values
10000000 loops, best of 3: 147 ns per loop
Auch eine nicht vorhandene Zahl muss natürlich immer alle Elemente durchlaufen.
Bei Sammlungen, die auf Hashing basieren (Sets, Dictionaries), kann dies *unabhängig* von der Größe der Sammlung immer in konstanter Zeit erreicht werden.
Edit: Noch einmal zur Verdeutlichung eine Reduktion der Anzahl um den Faktor 10 also von 10 Millionen auf eine Million Elemente. Man erkennt schön, wie der Listen basierte Zugriff sich *linear* um den Faktor reduziert (30ms vs 300ms), wohingegen der Mengen basierte Ansatz gleich geblieben ist:
Code: Alles auswählen
In [14]: some_value = 999999
In [15]: values = list(range(1000000))
In [16]: timeit some_value in values
10 loops, best of 3: 30.6 ms per loop
In [17]: values = set(range(1000000))
In [18]: timeit some_value in values
10000000 loops, best of 3: 145 ns per loop
Nein, eben nicht! (Das ist ja das tolle; das passiert übrigens auch bei Ausnahmen!)sfx2k hat geschrieben: Muss ich, wenn ein File in einer with-Anweisung geöffnet wird, dieses nicht auch wieder schließen?
Zuletzt geändert von Hyperion am Donnerstag 18. September 2014, 09:01, insgesamt 1-mal geändert.
Grund: Vergleichswerte ergänzt
Grund: Vergleichswerte ergänzt
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
@sfx2k: Drei Posts vorher hat ein `set` noch etwas gebracht weil der ``in``-Operator bei Listen die Liste linear, Element für Element, vergleicht, und ein `set()` diese Anfrage ”sofort” beantworten kann, ohne sich alle enthaltenen Element einzeln anschauen zu müssen. Wenn man nur über die Elemente itertiert, dann verwendet man diese Eigenschaft von `set` nicht. Dann könnte man nur noch argumentieren, dass man sicherstellen möchte, dass die Testworte alle unterschiedlich sind, was man bei den wenigen Worten noch ganz gut ohne Unterstützung vom Programm hinbekommt.
Man kann es auch unverschachtelt(er) schreiben, wenn man sich Namen für die Zwischenergebnisse ausdenkt.
Da gute Namen finden, in der Regel schwieriger ist als den Code an sich zu schreiben, spare ich mir das gerne.
Bei den regülären Ausdrücken benutze ich einen Generatorausdruck. Da hätte ich in der Tat `map()` oder `itertools.imap()` verwenden können.
Die ``with``-Anweisung sorgt dafür das egal wo und wie der Programmfluss den Block verlässt, die `__exit__()`-Methode auf dem Objekt aufgerufen wird das nach dem ``with``-Schlüsselwort erzeugt wird. Also in diesem Fall die Datei. Und bei Dateien ist eine `__exit__()`-Methode implementiert, welche die Datei schliesst. Das ist aber auch *das* Beispiel für die ``with``-Anweisung. Da sollte man eigentlich etwas zu finden.
Man kann es auch unverschachtelt(er) schreiben, wenn man sich Namen für die Zwischenergebnisse ausdenkt.
Code: Alles auswählen
def main():
to_delete = ['ich', 'du', 'er', 'sie', 'es']
lines = iter_lines('test.txt')
filtered_lines = ifilterfalse(create_line_test(to_delete), lines)
save_lines('test2.txt', filtered_lines)
Bei den regülären Ausdrücken benutze ich einen Generatorausdruck. Da hätte ich in der Tat `map()` oder `itertools.imap()` verwenden können.
Die ``with``-Anweisung sorgt dafür das egal wo und wie der Programmfluss den Block verlässt, die `__exit__()`-Methode auf dem Objekt aufgerufen wird das nach dem ``with``-Schlüsselwort erzeugt wird. Also in diesem Fall die Datei. Und bei Dateien ist eine `__exit__()`-Methode implementiert, welche die Datei schliesst. Das ist aber auch *das* Beispiel für die ``with``-Anweisung. Da sollte man eigentlich etwas zu finden.
@Hyperion und Blackjack:
Vielen Dank für diese detaillierten Erläuterungen. Das muss man aber auch erstmal wissen
Naja, Übung macht den Meister
@Blackjack:
Ich fürchte, dass ich im Suchen nach Python-Problemen noch keine Routine habe, also oft gar nicht weiß, nach was und wo ich suchen soll.
In diesem Fall habe ich bei Google nach 'python with file open close' gesucht.
Dabei habe ich mir sogar das erste Suchergebnis angesehen, aufgrund der vielen 'literalen' with im Text aber den Überblick verloren und die wesentliche Stelle einfach übersehen.
Vielen Dank für diese detaillierten Erläuterungen. Das muss man aber auch erstmal wissen
Naja, Übung macht den Meister
@Blackjack:
Ich fürchte, dass ich im Suchen nach Python-Problemen noch keine Routine habe, also oft gar nicht weiß, nach was und wo ich suchen soll.
In diesem Fall habe ich bei Google nach 'python with file open close' gesucht.
Dabei habe ich mir sogar das erste Suchergebnis angesehen, aufgrund der vielen 'literalen' with im Text aber den Überblick verloren und die wesentliche Stelle einfach übersehen.
It is good practice to use the with keyword when dealing with file objects. This has the advantage that the file is properly closed after its suite finishes, even if an exception is raised on the way.
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Naja, lernen ist ja nie verkehrt Hier kannst Du über das Konzept der Zeitkomplexität ein wenig nachlesen. Und hier gibt es einen Überblick über die Zeitkomplexität der Operationen bei den Standard-Containern von Python.sfx2k hat geschrieben:@Hyperion und Blackjack:
Vielen Dank für diese detaillierten Erläuterungen. Das muss man aber auch erstmal wissen
Naja, Übung macht den Meister
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
@sfx2k: Ich bin immer wieder erstaunt wie schnell die Leute heute zu Google greifen statt erst einmal in der jeweiligen Dokumentation zu schauen. ``with`` ist in der Python-Dokumentation. Beide Stellen die im Index verlinkt sind verweisen auch am Ende des Abschnitts auf das PEP mit der Spezifikation, Hintergründen, und Beispielen.
Wenn man Schlüsselwörter der Sprache oder etwas aus der Standardbibliothek sucht, dann ist der Index in der Python-Dokumentation sehr praktisch. Der ist auf fast allen Dokumentationsseiten oben rechts zu erreichen.
Wenn man Schlüsselwörter der Sprache oder etwas aus der Standardbibliothek sucht, dann ist der Index in der Python-Dokumentation sehr praktisch. Der ist auf fast allen Dokumentationsseiten oben rechts zu erreichen.
Background ist immer gut Danke!Hyperion hat geschrieben: Naja, lernen ist ja nie verkehrt Hier kannst Du über das Konzept der Zeitkomplexität ein wenig nachlesen. Und hier gibt es einen Überblick über die Zeitkomplexität der Operationen bei den Standard-Containern von Python.
Ich habe zuerst bei Google geschaut, daBlackJack hat geschrieben:@sfx2k: Ich bin immer wieder erstaunt wie schnell die Leute heute zu Google greifen statt erst einmal in der jeweiligen Dokumentation zu schauen. ``with`` ist in der Python-Dokumentation. Beide Stellen die im Index verlinkt sind verweisen auch am Ende des Abschnitts auf das PEP mit der Spezifikation, Hintergründen, und Beispielen.
1. die PythonDokumentation nicht wirklich 'einfach' ist
2. man bei Google Verweise auf die genaue Problemstellung findet, und sich nicht erst duch drei Seiten Beschreibung zu einem Modul o.ä. hangeln muss, bis man das Gesuchte gefunden hat
Ich habe bspw. in der Online-Ausgabe im Quick-Search-Feld nach with gesucht; es wurde aber kein Verweis auf das with-Statement angezeigt: https://docs.python.org/3.4/search.html ... ea=default
Super! Danke für den Tipp. Darüber findet man ja wirklich schnell etwasBlackJack hat geschrieben: Wenn man Schlüsselwörter der Sprache oder etwas aus der Standardbibliothek sucht, dann ist der Index in der Python-Dokumentation sehr praktisch. Der ist auf fast allen Dokumentationsseiten oben rechts zu erreichen.
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Huch... ich empfinde die Doku von Python immer als eine der besten überhaupt! Imho sehr gut gegliedert, gute Beispiele und verständliche Beschreibungensfx2k hat geschrieben: 1. die PythonDokumentation nicht wirklich 'einfach' ist
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
Es mag gut sein, dass die Doku eine der besten ist.Hyperion hat geschrieben:Huch... ich empfinde die Doku von Python immer als eine der besten überhaupt! Imho sehr gut gegliedert, gute Beispiele und verständliche Beschreibungensfx2k hat geschrieben: 1. die PythonDokumentation nicht wirklich 'einfach' ist
Da die Delphi-Hilfe aber ganz anders aufgebaut ist, finde ich mich noch nicht so wirklich zurecht.
Wird schon...