Grundlage für größeres Programm - was verbessern?

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.
rolgal_reloaded
User
Beiträge: 309
Registriert: Dienstag 24. Oktober 2006, 19:31

Grundlage für größeres Programm - was verbessern?

Beitragvon rolgal_reloaded » Dienstag 17. April 2007, 11:00

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
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Beitragvon Zap » Dienstag 17. April 2007, 11:18

Sieht nach HTML aus, da würden dann aber noch einige fehlen.
Nur als Beispiel:

Code: Alles auswählen

& für &
< für <
> für >
usw...

Ich denke das es da bestimmt fertige module im html Bereich gibt.
Würde vielleicht da mal ein bisschen forschen.
rolgal_reloaded
User
Beiträge: 309
Registriert: Dienstag 24. Oktober 2006, 19:31

Beitragvon rolgal_reloaded » Dienstag 17. April 2007, 11:40

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
BlackJack

Beitragvon BlackJack » Dienstag 17. April 2007, 12:20

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.
rolgal_reloaded
User
Beiträge: 309
Registriert: Dienstag 24. Oktober 2006, 19:31

Beitragvon rolgal_reloaded » Dienstag 17. April 2007, 12:34

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
BlackJack

Beitragvon BlackJack » Dienstag 17. April 2007, 12:56

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.
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Beitragvon HWK » Dienstag 17. April 2007, 13:07

Schau Dir mal das Standardmodul 'htmlentitydefs' an. Es enthält bereits fertige Dicts.
MfG
HWK
rolgal_reloaded
User
Beiträge: 309
Registriert: Dienstag 24. Oktober 2006, 19:31

Beitragvon rolgal_reloaded » Dienstag 17. April 2007, 13:30

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
rolgal_reloaded
User
Beiträge: 309
Registriert: Dienstag 24. Oktober 2006, 19:31

Beitragvon rolgal_reloaded » Dienstag 17. April 2007, 14:27

...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
BlackJack

Beitragvon BlackJack » Dienstag 17. April 2007, 14:35

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.
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

Beitragvon EnTeQuAk » Dienstag 17. April 2007, 14:57

[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]
Mephisto
User
Beiträge: 28
Registriert: Mittwoch 17. Januar 2007, 15:52

Beitragvon Mephisto » Dienstag 17. April 2007, 15:33

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
rolgal_reloaded
User
Beiträge: 309
Registriert: Dienstag 24. Oktober 2006, 19:31

Beitragvon rolgal_reloaded » Dienstag 17. April 2007, 15:58

@BlackJack,

ja das geht mir ein bzw. kann mir vorstellen, dass das allgemein gut verständlich so ist.

Danke nochmal

LG

rolgal
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Beitragvon birkenfeld » Dienstag 17. April 2007, 16:07

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())``.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
rolgal_reloaded
User
Beiträge: 309
Registriert: Dienstag 24. Oktober 2006, 19:31

Beitragvon rolgal_reloaded » Dienstag 17. April 2007, 16:45

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

Wer ist online?

Mitglieder in diesem Forum: Bing [Bot]