Seite 1 von 2
Grundlage für größeres Programm - was verbessern?
Verfasst: Dienstag 17. April 2007, 11:00
von rolgal_reloaded
Hallo zusammen,
nachstehender Code soll ein Ausgangsbeispiel für ein "größeres Programm" werden.
Deutsche Namen sind Absicht. Würdet ihr sonst irgendwas anders machen, wenn ja, warum?
Code: Alles auswählen
text = """Österreich ist ein schönes Land.
Grüße an alle aus dem Ländle."""
umlaute_codecs = {"Ö":"Ö","ö":"ö",
"Ä":"Ä","ä":"ä",
"Ü":"Ü","ü":"ü",
"ß":"szlig"}
for zeichen in text:
if zeichen in umlaute_codecs.keys():
text = text.replace(zeichen,umlaute_codecs[zeichen])
print text
Vielen Dank im Voraus
rolgal_reloaded
Verfasst: Dienstag 17. April 2007, 11:18
von Zap
Sieht nach HTML aus, da würden dann aber noch einige fehlen.
Nur als Beispiel:
Ich denke das es da bestimmt fertige module im html Bereich gibt.
Würde vielleicht da mal ein bisschen forschen.
Verfasst: Dienstag 17. April 2007, 11:40
von rolgal_reloaded
Hallo zap,
ja klar fehlen da noch einige. Das war jetzt aber nicht wichtig.
Mir ging es um die Vorgangsweise.
Dictionary,
Formulierung der Schleife usw.
Wobei ich nicht meine es in eine Funktion zu packen usw.
LG
rolgal
Verfasst: Dienstag 17. April 2007, 12:20
von BlackJack
Das ist sehr fragil weil `text` keine Zeichen sondern Bytes enthält, und das Dictionary auch. Wenn man mit Zeichen arbeiten will, insbesondere ausserhalb von ASCII, sollte man sich mit Unicode auseinandersetzen.
Beim Wert zum 'ß' fehlen '&' und ';'.
Bei der Schleife gibt's eigentlich zu allen drei Zeilen etwas zu sagen.
Erstmal die Schleife: Warum muss man sich jedes Zeichen anschauen? Mal angenommen der `text` ist 'äbbä', dann wird die Schleife 4-mal durchlaufen. Beim ersten mal werden alle 'ä' ersetzt, beim 4. mal auch wieder, obwohl gar keine mehr vorhanden sind.
In der ``if``-Abfrage ist der Aufruf von `keys()` nicht nur überflüssig, ``in`` ist auf Dictionaries schon so definiert, das auf Schlüssel getestet wird, sondern es wird für jedes Zeichen im Text eine Liste mit den Schlüsseln erzeugt, linear(!) durchsucht und dann wieder weggeworfen.
Die letzte Zeile ist vertretbar, wenn die äussere Schleife besser wäre, allerdings wird für jedes `replace()` der gesamte Text durchlaufen. Mit `re.sub()` liesse sich das eventuell mit linearer Laufzeit lösen.
Man sollte es mindestens hierauf beschränken:
Code: Alles auswählen
for sonderzeichen, entity in umlaute_codecs.iteritems():
text = text.replace(sonderzeichen, entity)
Der Name `umlaute_codecs` ist nicht ganz passend, da auch ein 'ß' enthalten ist.
Verfasst: Dienstag 17. April 2007, 12:34
von rolgal_reloaded
BlackJack hat geschrieben:Das ist sehr fragil weil `text` keine Zeichen sondern Bytes enthält, und das Dictionary auch. Wenn man mit Zeichen arbeiten will, insbesondere ausserhalb von ASCII, sollte man sich mit Unicode auseinandersetzen.
Beim Wert zum 'ß' fehlen '&' und ';'.
Das war ein Versehen.
BlackJack hat geschrieben:
Bei der Schleife gibt's eigentlich zu allen drei Zeilen etwas zu sagen.
Erstmal die Schleife: Warum muss man sich jedes Zeichen anschauen? Mal angenommen der `text` ist 'äbbä', dann wird die Schleife 4-mal durchlaufen. Beim ersten mal werden alle 'ä' ersetzt, beim 4. mal auch wieder, obwohl gar keine mehr vorhanden sind.
In der ``if``-Abfrage ist der Aufruf von `keys()` nicht nur überflüssig, ``in`` ist auf Dictionaries schon so definiert, das auf Schlüssel getestet wird, sondern es wird für jedes Zeichen im Text eine Liste mit den Schlüsseln erzeugt, linear(!) durchsucht und dann wieder weggeworfen.
?? Meintest du vielleicht:
``in`` ist auf Dictionaries schon so definiert, dass nicht auf Schlüssel getestet wird, sondern es wird für jedes Zeichen im Text eine Liste mit den ......
Sonst versteh ich es nämlich nicht, also den Satz ansich nicht.
BlackJack hat geschrieben:
Die letzte Zeile ist vertretbar, wenn die äussere Schleife besser wäre, allerdings wird für jedes `replace()` der gesamte Text durchlaufen. Mit `re.sub()` liesse sich das eventuell mit linearer Laufzeit lösen.
Man sollte es mindestens hierauf beschränken:
Code: Alles auswählen
for sonderzeichen, entity in umlaute_codecs.iteritems():
text = text.replace(sonderzeichen, entity)
Das ist cool!
BlackJack hat geschrieben:
Der Name `umlaute_codecs` ist nicht ganz passend, da auch ein 'ß' enthalten ist.
Ja logo, ich habe zuerst nur mit Umlauten rumgemacht.....dann erst das ß hizugefügt. Sinnvoll natürlich es anders zu benennen.
Danke für den Hinweis.
LG
rolgal
Verfasst: Dienstag 17. April 2007, 12:56
von BlackJack
rolgal_reloaded hat geschrieben:BlackJack hat geschrieben:In der ``if``-Abfrage ist der Aufruf von `keys()` nicht nur überflüssig, ``in`` ist auf Dictionaries schon so definiert, das auf Schlüssel getestet wird, sondern es wird für jedes Zeichen im Text eine Liste mit den Schlüsseln erzeugt, linear(!) durchsucht und dann wieder weggeworfen.
?? Meintest du vielleicht:
``in`` ist auf Dictionaries schon so definiert, dass nicht auf Schlüssel getestet wird, sondern es wird für jedes Zeichen im Text eine Liste mit den ......
Sonst versteh ich es nämlich nicht, also den Satz ansich nicht.
Ich meinte es schon so wie's da steht. Aber den Satz kann sehr leicht falsch verstehen. Ich sollte mir so lange Sätze mit vielen Kommata abgewöhnen.
Was bei Dir passiert: Für jedes Zeichen in `text` wird eine Liste mit den Schlüsseln erzeugt (`keys()`) und auf diese *Liste* wird dann der ``in``-Operator angewandt. Das bedeutet es wird für jedes Zeichen diese Liste erzeugt und linear nach `zeichen` durchsucht.
Der ``in``-Operator auf Dictionaries ist aber schon so definiert, das er das Objekt links vom Operator in den Schlüsseln sucht. Das allerdings ohne eine temporäre Liste zu erzeugen und auch nicht linear sondern in O(1)-Zeit.
Verfasst: Dienstag 17. April 2007, 13:07
von HWK
Schau Dir mal das Standardmodul 'htmlentitydefs' an. Es enthält bereits fertige Dicts.
MfG
HWK
Verfasst: Dienstag 17. April 2007, 13:30
von rolgal_reloaded
Hi BlackJack,
so toll bzw. sinnig das mit iteritems() ist, so schwierig ist es für Anfänger sich was konkretes darunter vorzustellen.
<dictionary-itemiterator object at 0x00C441A0>
Wie soll ich das ausdeutschen??
Vor allem wenn mir selbst damit noch nicht alles klar ist, ggg.
@HWK
Danke für den Tipp! Ich möchte trotzdem mal etwas damit rumspielen.
LG
rolgal_reloaded
Verfasst: Dienstag 17. April 2007, 14:27
von rolgal_reloaded
...nochmal ein Vorschlag, man wenn man nicht dauernd programmiert,...dann ist es mühsam immer das beste parat zu haben.
Mit iteritems() bin ich nicht ganz glücklich. Ist folgende Lösung nicht ebenso vertretbar und wesentlich besser wie mein erster Vorschlag?
Code: Alles auswählen
text = """Österreich ist ein schönes Land.
Grüße an alle aus dem Ländle."""
sonderzeichen_codecs = {"Ö":"Ö","ö":"ö",
"Ä":"Ä","ä":"ä",
"Ü":"Ü","ü":"ü",
"ß":"ß"}
for sonderzeichen, entity in sonderzeichen_codecs.items():
text = text.replace(sonderzeichen, entity)
Also nur über die Liste die items zurückgibt iterieren, anstatt ein Iterationsobjekt zu erzeugen.
Oder ist das so ein immenser Nachteil?
LG
rolgal_reloaded
Verfasst: Dienstag 17. April 2007, 14:35
von BlackJack
Das ist ein Iterator über die Elemente in dem Dictionary, also über (Schlüssel, Wert)-Tupel. Und das kann man doch ganz einfach zeigen und ausprobieren:
Code: Alles auswählen
In [87]: a = umlaute_codecs.iteritems()
In [88]: a
Out[88]: <dictionary-itemiterator object at 0xb772c8e0>
In [89]: a.next()
Out[89]: ('\xc3\xb6', 'ö')
In [90]: a.next()
Out[90]: ('\xc3\xbc', 'ü')
In [91]: a.next()
Out[91]: ('\xc3\xa4', 'ä')
Iteratoren oder "iterables" im allgemeinen ist ein extrem grundlegendes Konzept von Python, schliesslich baut die am meisten genutzte Schleifenform darauf auf.
Ansonsten kannst Du auch sagen, dass ist wie die `items()`-Methode, nur speicherschonender:
Code: Alles auswählen
In [93]: umlaute_codecs.items()
Out[93]:
[('\xc3\xb6', 'ö'),
('\xc3\xbc', 'ü'),
('\xc3\xa4', 'ä'),
('\xc3\x9f', 'szlig'),
('\xc3\x9c', 'Ü'),
('\xc3\x84', 'Ä'),
('\xc3\x96', 'Ö')]
Edit: In Python 3.0 sollen die "normalen" Methoden auf `dict()` verschwinden und durch durch die `iter*()`-Varianten ersetzt werden. Dann verhält sich also `items()` so wie `iteritems()` heute.
Verfasst: Dienstag 17. April 2007, 14:57
von EnTeQuAk
[offtopic]
Edit: In Python 3.0 sollen die "normalen" Methoden auf `dict()` verschwinden und durch durch die `iter*()`-Varianten ersetzt werden. Dann verhält sich also `items()` so wie `iteritems()` heute.
bleiben aber bestehen, oder? Ich meine... sonst wär ja einiges nicht kompatibel

und btw: gibt es schon nen genauen Zeitplan für 3.0? (sollen ja einige Interessante Sachen kommen, hab ich mal irgentwo gelesen)
[/offtopic]
Verfasst: Dienstag 17. April 2007, 15:33
von Mephisto
Soweit ich weis, hat man bei Python 3k nicht vor unbedingt rückwärtskompatibel zu bleiben, um gewisse Dinge anders zu machen als im Python2.x-Zweig wo man ja auf kompatibilität Wert legt.
Ausserdem wird es Python2.x vermutlich eine ganze weile paralell zu Python 3k geben.
Hoffe das war kein stuss, aber wenn korrigiert mich eh jemand
greets meph
Verfasst: Dienstag 17. April 2007, 15:58
von rolgal_reloaded
@BlackJack,
ja das geht mir ein bzw. kann mir vorstellen, dass das allgemein gut verständlich so ist.
Danke nochmal
LG
rolgal
Verfasst: Dienstag 17. April 2007, 16:07
von birkenfeld
EnTeQuAk hat geschrieben:[offtopic]
Edit: In Python 3.0 sollen die "normalen" Methoden auf `dict()` verschwinden und durch durch die `iter*()`-Varianten ersetzt werden. Dann verhält sich also `items()` so wie `iteritems()` heute.
bleiben aber bestehen, oder? Ich meine... sonst wär ja einiges nicht kompatibel

und btw: gibt es schon nen genauen Zeitplan für 3.0? (sollen ja einige Interessante Sachen kommen, hab ich mal irgentwo gelesen)
[/offtopic]
Nein, natürlich bleiben die alten Methoden nicht. Sonst wärs ja sinnlos...
Wenn du in 3k eine Liste von Items brauchst, nimm ``list(x.items())``.
Verfasst: Dienstag 17. April 2007, 16:45
von rolgal_reloaded
BlackJack hat geschrieben:
Iteratoren oder "iterables" im allgemeinen ist ein extrem grundlegendes Konzept von Python, schliesslich baut die am meisten genutzte Schleifenform darauf auf.
Ansonsten kannst Du auch sagen, dass ist wie die `items()`-Methode, nur speicherschonender:
Lässt das den Schluss zu, dass man dann eigentlich statt keys() und values() immer iterkeys() und itervalues() verwenden sollte - sofern man über die Schlüssel bzw. Werte iterieren will.
Stimmt weiters diese Aussage: items() erzeugt sofort eine ganze Liste der Schlüssel und Werte eines Dictionaries und iteritems() stellt immer nur ein Schlüssel Wertpaar aus dem Dictionary zur Verfügung, quasi das aktuelle.
LG
rolgal_reloaded
Verfasst: Dienstag 17. April 2007, 16:49
von Mephisto
Ich würde nein sagen, da es noch eine ganze Weile dauern wird bis Python 3000 erscheint. Und eine solch einfache Änderung bewältigt jeder Texteditor der über eine Suchen und Ersetzen Funktion verfügt
greets meph
Verfasst: Dienstag 17. April 2007, 16:52
von BlackJack
@rolgal_reloaded: Jup, die Aussagen stimmen so.
Wie immer gibt's Ausnahmen: Wenn Du über Schlüssel, Werte oder Paare davon iterierst und die das Dictionary in der Schleife veränderst, dann kann es Probleme geben. Ähnlich wie bei Listen über die man nicht (vorwärts) iterieren sollte wenn man in der Schleife Listenelemente entfernt.
Verfasst: Dienstag 17. April 2007, 18:57
von rolgal_reloaded
BlackJack hat geschrieben:@rolgal_reloaded: Jup, die Aussagen stimmen so.
Wie immer gibt's Ausnahmen: Wenn Du über Schlüssel, Werte oder Paare davon iterierst und die das Dictionary in der Schleife veränderst, dann kann es Probleme geben. Ähnlich wie bei Listen über die man nicht (vorwärts) iterieren sollte wenn man in der Schleife Listenelemente entfernt.
Denke das habe ich.
Dann stimmt wohl auch, dass das aktuelle Element nachdem es in der Schleife abgearbeitet wurde, sofort aus dem Speicher gelöscht wird, oder?
Sonst wäre es wohl kein so immenser Performancegewinn
Wenn weiters richtig, dann sind die itermethoden auch sehr interessant, wenn innerhalb einer Endlosschleife (while True) z. B. bei einem Vokabeltrainer diese auf Grund einer bestimmten Bedingung verlassen wird (10 Vokabeln hintereinander richtig - Lektionswechsel - neues Dict laden).
Klar und richtig was ich meine?
LG
rolgal_reloaded
Verfasst: Dienstag 17. April 2007, 19:45
von BlackJack
Aus dem Speicher gelöscht wird das Element nicht, es ist ja immer noch im Dictionary. Die Elemente werden ja nur an die Namen in der Schleife gebunden und nicht kopiert.
Verfasst: Dienstag 17. April 2007, 20:42
von rolgal_reloaded
Ich meinte natürlich nicht, dass es aus dem Dictionary gelöscht wird.
Aber aus dem Arbeitsspeicher heisst ja nicht aus dem Dictionary
Oder habe ich da technisch was falsch verstanden?
Also ich meine: das muss ja speichertechnisch irgendwie anders verwaltet werden, wie kann es sonst zu einer Steigerung der Performance kommen?
Denn es geht ja darum, dass nicht die ganze Liste auf einmal erzeugt wird bzw. immer nur das aktuelle Element zur Verfügung steht.
Schwierig das in Worte zu fassen
LG
r_r