Hallo,
ich habe "aus Spaß" ein Modul geschrieben, was Text nach Morsecode "übersetzt" und auch Morsecode nach Text. Interessanterweise gibt es - zumindest im Cheese-Shop - dazu nur ein Modul, welches aus einer Zeile Code und einen Dict für Mapping besteht... Das Modul kann auch nur Text -> Morse, nicht umgekehrt.
Der Code ist hier:
http://bazaar.launchpad.net/~noisefloor ... pymorse.py
Die Docstrings sind vollständig.
Getestet habe ich bis jetzt "nur" mit Python 2.7.
Verbesserungsverschläge sind willkommen
Eine Frage direkt: würde ihr die print-Anweisung auch so verwenden oder hier lieber auf's Logging-Modul zurückgreifen?
Gruß, noisefloor
pyMorse - Text -> Morsecode und Morsecode -> Text
- noisefloor
- User
- Beiträge: 3856
- Registriert: Mittwoch 17. Oktober 2007, 21:40
- Wohnort: WW
- Kontaktdaten:
@noisefloor: Bei den Ausnahmen hätte ich eine Klassenhierarchie erstellt. Mindestens mal eine Basisklasse von der alle anderen abgleitet werden, damit man nicht gezwungen ist wirklich alle in einem ``except`` aufzuführen wenn man nur daran interessiert ist grundsätzlich zu wissen ob es fehlgeschlagen ist.
Du machst alles möglich an Zeichen konfigurierbar, nur nicht den kurzen und den langen Pieps selbst.
Die Schleife am Ende der `__init__()` würde auf Klassenebene nur einmal ausgeführt werden und nicht bei jedem Erstellen eines `Morse`-Exemplars.
Die ``print``\s hätte ich in der Tat über Logging gelöst, dann kann man sie abschalten.
``else: pass``?
Wenn man bei verknüpften Bedingungen ein bisschen auf die Reihenfolge achtet kann man ab und zu Rechenzeit sparen. Also zum Beispiel erst prüfen ob man im `strict_mode` ist und dann erst die Daten untersuchen. Und das ganze auch so anordnen, dass man nicht mehrfach das gleiche ausrechnen muss und/oder in ``elif``-Zweigen teilweise die gleiche Bedingung stehen hat wie im Test für den Zweig davor. Beispiel:
Ist von den Bedingungen her IMHO auch einfacher verständlich ausgedrückt.
Statt den `KeyError` abzufangen hätte man anstelle des []-Zugriffs auch die `get()`-Methode verwenden können.
In `is_valid_morse_code()` könnte man `all()` und einen Generatorausdruck verwenden.
Der Rückgabewert von `is_valid_input_text()` ist unnötig kompliziert. Es würde reichen einfach die gefundenen ungültigen Zeichen zurück zu geben. Der Wahrheitswert ergibt sich daraus ja automatisch ist also redundant. Ein `set()` wäre hier vielleicht besser als eine Liste.
Du machst alles möglich an Zeichen konfigurierbar, nur nicht den kurzen und den langen Pieps selbst.
Die Schleife am Ende der `__init__()` würde auf Klassenebene nur einmal ausgeführt werden und nicht bei jedem Erstellen eines `Morse`-Exemplars.
Die ``print``\s hätte ich in der Tat über Logging gelöst, dann kann man sie abschalten.
``else: pass``?
Wenn man bei verknüpften Bedingungen ein bisschen auf die Reihenfolge achtet kann man ab und zu Rechenzeit sparen. Also zum Beispiel erst prüfen ob man im `strict_mode` ist und dann erst die Daten untersuchen. Und das ganze auch so anordnen, dass man nicht mehrfach das gleiche ausrechnen muss und/oder in ``elif``-Zweigen teilweise die gleiche Bedingung stehen hat wie im Test für den Zweig davor. Beispiel:
Code: Alles auswählen
if not test(data) and strict_mode:
error()
elif not test(data) and not strict_mode:
warning()
#
# Besser:
#
if not test(data):
if strict_mode:
error()
else:
warning()
Statt den `KeyError` abzufangen hätte man anstelle des []-Zugriffs auch die `get()`-Methode verwenden können.
In `is_valid_morse_code()` könnte man `all()` und einen Generatorausdruck verwenden.
Der Rückgabewert von `is_valid_input_text()` ist unnötig kompliziert. Es würde reichen einfach die gefundenen ungültigen Zeichen zurück zu geben. Der Wahrheitswert ergibt sich daraus ja automatisch ist also redundant. Ein `set()` wäre hier vielleicht besser als eine Liste.
- noisefloor
- User
- Beiträge: 3856
- Registriert: Mittwoch 17. Oktober 2007, 21:40
- Wohnort: WW
- Kontaktdaten:
Hallo,
Gruß, noisefloor
Verstehe gerade nicht, wie du das genau meinst... Kannst du das bitte ein bisschen ausführlicher darstellen?BlackJack hat geschrieben:@noisefloor: Bei den Ausnahmen hätte ich eine Klassenhierarchie erstellt. Mindestens mal eine Basisklasse von der alle anderen abgleitet werden, damit man nicht gezwungen ist wirklich alle in einem ``except`` aufzuführen wenn man nur daran interessiert ist grundsätzlich zu wissen ob es fehlgeschlagen ist.
Das ist - im Moment - Absicht. Ich hatte darüber nachgedacht, aber für den Moment verworfen. Vielleicht baue ich das noch ein...BlackJack hat geschrieben:Du machst alles möglich an Zeichen konfigurierbar, nur nicht den kurzen und den langen Pieps selbst.
Das stimmt... dann müsste die Funktion aber `is_invalid_input_text`heißen, weil ein Rückgabewert von `True` ja dann die nicht-Gültigkeit kennzeichnet Werde ich aber so machen, dass ist besser als das Tuple, was im Moment zurückgegeben wird.BlackJack hat geschrieben:Der Rückgabewert von `is_valid_input_text()` ist unnötig kompliziert. Es würde reichen einfach die gefundenen ungültigen Zeichen zurück zu geben. Der Wahrheitswert ergibt sich daraus ja automatisch ist also redundant.
Gruß, noisefloor
@noisefloor: Ad Ausnahmeklassenhierarchie: Im einfachsten Fall eine `MorseError`-Ausnahme von der alle anderen erben. Damit man als Benutzer der Objekte eine einfache Möglichkeit hat alle Ausnahmen zu behandeln ohne tatsächlich alle hinschreiben zu müssen. Im Moment müsste man ja so etwas hier schreiben:
Wo man eigentlich lieber das hier schreiben würde:
Code: Alles auswählen
except (
MorseCodeError, InvalidCharSeparatorError, InvalidWordSeparatorError
) as error:
print 'Something went wrong:', error
Code: Alles auswählen
except MorseError as error:
print 'Something went wrong:', error
- noisefloor
- User
- Beiträge: 3856
- Registriert: Mittwoch 17. Oktober 2007, 21:40
- Wohnort: WW
- Kontaktdaten:
Hallo,
aktualisierte Version ist im Repo.
Logging statt print ist nach wie vor nicht drin, kommt noch.
Frage - stelle mich da gerade blöd an: Wie bekomme ich den die überlangen Zeilen bei
weg, _ohne_ dass `\n` in der Ausgabe mit angezeigt werden (wenn diese zwecks Zeilenumbruch in den Strings drin wären?
Gruß, noisefloor
aktualisierte Version ist im Repo.
Logging statt print ist nach wie vor nicht drin, kommt noch.
Frage - stelle mich da gerade blöd an: Wie bekomme ich den die überlangen Zeilen bei
Code: Alles auswählen
raise MorseError(...)
Gruß, noisefloor
@noisefloor: was soll den der Quatsch in Zeile 282? So war das mit dem »get« von BlackJack nicht gemeint.
In Zeile 277: was soll die List-Comprehension?
In Zeile 275 produzierst Du zur Zeit einen NameError.
In Zeile 329 hast Du eine interessante Art »all« zu benutzen. Sobald »char_sep« oder »word_sep« aus mehreren unterschiedlichen Zeichen bestehen funktioniert die Methode auch nicht mehr.
»is_not_valid_input_text« hieße besser »find_invalid_characters« und wenn Du schon »set«s benutzt, dann konsequent:
Und in »_check_separators« würde ich auch die Schleifen weglassen:
In Zeile 277: was soll die List-Comprehension?
In Zeile 275 produzierst Du zur Zeit einen NameError.
Code: Alles auswählen
return self.word_sep.join(
self.char_sep.join(
self.CHAR_TO_MORSE.get(char, self.missing_char_placeholder) for char in word)
for word in text.split())
Code: Alles auswählen
return morse_code.replace(self.word_sep,'').replace(self.char_sep,'').replace('.','').replace('-','')
Code: Alles auswählen
return ','.join(set(text)-set(self.CHAR_TO_MORSE)-set(' '))
Code: Alles auswählen
if set('-.')&set(self.char_sep): …
- noisefloor
- User
- Beiträge: 3856
- Registriert: Mittwoch 17. Oktober 2007, 21:40
- Wohnort: WW
- Kontaktdaten:
Hallo,
Danke für die Tipps. Habe jetzt soweit alles eingearbeitet (wenn ich nix übersehen habe...). Aktuelle rev4 ist im Repo.
Das Modul heißt jetzt übrigesn pyMorseCode, weil es schon pyMorse gibt (Link: http://www.openrobots.org/morse/doc/latest/pymorse.html). Hat zwar nix mit Morsen zu tun, hat aber den gleichen Namen...
logging statt print kommt noch, kann aber ein wenig dauern. Und die Docstrings muss ich noch mal prüfen.
Muss erst Mal ein paar produktive Sachen machen.
Gruß, noisefloor
Danke für die Tipps. Habe jetzt soweit alles eingearbeitet (wenn ich nix übersehen habe...). Aktuelle rev4 ist im Repo.
Das Modul heißt jetzt übrigesn pyMorseCode, weil es schon pyMorse gibt (Link: http://www.openrobots.org/morse/doc/latest/pymorse.html). Hat zwar nix mit Morsen zu tun, hat aber den gleichen Namen...
logging statt print kommt noch, kann aber ein wenig dauern. Und die Docstrings muss ich noch mal prüfen.
Muss erst Mal ein paar produktive Sachen machen.
Gruß, noisefloor
- noisefloor
- User
- Beiträge: 3856
- Registriert: Mittwoch 17. Oktober 2007, 21:40
- Wohnort: WW
- Kontaktdaten:
Hallo,
die Launchpad-Projektseite ist jetzt auch umbenannt: http://launchpad.net/pymorsecode
Das Repo ist jetzt hier: https://code.launchpad.net/~noisefloor/ ... code/trunk
In der aktuellsten Version ist jetzt auch print durch's Logging-Modul ersetzt.
Wenn noch jemand Anmerkung oder Verbesserungsvorschläge hat -> bitte
Gruß, noisefloor
die Launchpad-Projektseite ist jetzt auch umbenannt: http://launchpad.net/pymorsecode
Das Repo ist jetzt hier: https://code.launchpad.net/~noisefloor/ ... code/trunk
In der aktuellsten Version ist jetzt auch print durch's Logging-Modul ersetzt.
Wenn noch jemand Anmerkung oder Verbesserungsvorschläge hat -> bitte
Gruß, noisefloor
@noisefloor: für meinen Geschmack erzeugst Du in »from_morse« noch zu viele Listen:
Code: Alles auswählen
…
def _char_from_morse_strict(self, char):
try:
return self.MORSE_TO_CHAR[char]
except KeyError:
raise MorseCodeError('Illegal morse code sequence',
'Morse code contains a non-valid code sequence')
def _char_from_morse_lazy(self, char):
try:
return self.MORSE_TO_CHAR[char]
except KeyError:
self.logger.warning('Found illegal morse code sequence {0}. '
'Will use {1} as place holder instead'.format(
char, self.missing_morse_code_placeholder))
return self.missing_morse_code_placeholder
def from_morse(self, morse_code):
'''args: morse_code
This function translates the given morse_code "morse_code" back to
text. Prior to translation, the function "is_valid_morse_code" is
called to check whether the morse code contains valid characters for
code representation only.
In case "strict_mode" is set to True (the default), an exception will
be raised. In case it is set to False, the class attribute
"missing_morse_code_placeholder" will be used in the translated text
for non-translatable sequences of morse code.
'''
self._check_separators()
#test on invalid characters in morse code
if self.is_valid_morse_code(morse_code):
raise MorseCodeError('Morse Code error',
'Morse code contains invalid characters')
get_char = self._char_from_morse_strict if self.strict_mode else self._char_from_morse_lazy
#decode morse code into characters
return ' '.join(
''.join(map(get_char, word.split(self.char_sep)))
for word in morse_code.split(self.word_sep))
…
- noisefloor
- User
- Beiträge: 3856
- Registriert: Mittwoch 17. Oktober 2007, 21:40
- Wohnort: WW
- Kontaktdaten:
Hallo,
@Sirius3: Danke für den Input - ist in weiten Teilen übernommen
Dann wäre das Modul erst Mal fertig.
Habe hier doch eine Menge gelernt - auch wenn mein ursprünglicher Code im Prinzip das gleiche Resultat geliefet hat, ist die jetzige Version doch kompakter und eleganter.
Danke noch Mal an alle, die hier Tipps gegeben haben.
Gruß, noisefloor
@Sirius3: Danke für den Input - ist in weiten Teilen übernommen
Dann wäre das Modul erst Mal fertig.
Habe hier doch eine Menge gelernt - auch wenn mein ursprünglicher Code im Prinzip das gleiche Resultat geliefet hat, ist die jetzige Version doch kompakter und eleganter.
Danke noch Mal an alle, die hier Tipps gegeben haben.
Gruß, noisefloor
Hallo,
Auch wenn du sagst, dass du nur diese ITU-R M.1677-1-Empfehlung (ich hoffe, ich habe sie richtig kopiert ) unterstützt, wäre es doch eventuell trotzdem noch interessant, auch einen erweiterten Zeichensatz zu unterstützen, oder (Also Umlaute usw)?
Man könnte dann eventuell einen strengen Modus und einen erweiterten Modus unterstützen.
Außerdem könnte ich auch komplett anderen Morsecode für Japanisch liefern
Auch wenn du sagst, dass du nur diese ITU-R M.1677-1-Empfehlung (ich hoffe, ich habe sie richtig kopiert ) unterstützt, wäre es doch eventuell trotzdem noch interessant, auch einen erweiterten Zeichensatz zu unterstützen, oder (Also Umlaute usw)?
Man könnte dann eventuell einen strengen Modus und einen erweiterten Modus unterstützen.
Außerdem könnte ich auch komplett anderen Morsecode für Japanisch liefern
- noisefloor
- User
- Beiträge: 3856
- Registriert: Mittwoch 17. Oktober 2007, 21:40
- Wohnort: WW
- Kontaktdaten:
Hallo,
ich hatte darüber nachgedacht, dann aber verworfen - eben weil's nicht standardisiert ist.
Außerdem gibt es auch noch den "alten" Morse-Code (sieht http://en.wikipedia.org/wiki/Morse_code ... nd_history. Da ist aber das Problem, dass die Null ein laaaaaaang ist und sich IMHO nicht wirklich mit den ASCII Zeichen abbilden lässt.
Gruß, noisefloor
ich hatte darüber nachgedacht, dann aber verworfen - eben weil's nicht standardisiert ist.
Außerdem gibt es auch noch den "alten" Morse-Code (sieht http://en.wikipedia.org/wiki/Morse_code ... nd_history. Da ist aber das Problem, dass die Null ein laaaaaaang ist und sich IMHO nicht wirklich mit den ASCII Zeichen abbilden lässt.
Gruß, noisefloor
Hm, naja, aber ich finde ein unstandardisiertes, aber trotzdem unterstütztes Format doch besser. Das muss sich ja nicht ausschließen, notfalls könnte man doch auch mehrere Versionen anbieten Bzw. einfach das meistbenutzte Format nutzen.noisefloor hat geschrieben:Hallo,
ich hatte darüber nachgedacht, dann aber verworfen - eben weil's nicht standardisiert ist.
Außerdem gibt es auch noch den "alten" Morse-Code (sieht http://en.wikipedia.org/wiki/Morse_code ... nd_history. Da ist aber das Problem, dass die Null ein laaaaaaang ist und sich IMHO nicht wirklich mit den ASCII Zeichen abbilden lässt.
Gruß, noisefloor
Auch wenn pyMorseCode ja ganz gut ist, kommt mir das daher irgendwie ein wenig unvollständig vor. Etwas schade, wie ich finde.
- noisefloor
- User
- Beiträge: 3856
- Registriert: Mittwoch 17. Oktober 2007, 21:40
- Wohnort: WW
- Kontaktdaten:
Hallo,
fühl' dich frei eine Patch einzureichen oder zu forken.
Die "Übersetzung" Morse-Code <-> Text läuft ja über ein Dict, d.h. ist einfach erweiterbar.
Gruß, noisefloor
fühl' dich frei eine Patch einzureichen oder zu forken.
Die "Übersetzung" Morse-Code <-> Text läuft ja über ein Dict, d.h. ist einfach erweiterbar.
Gruß, noisefloor