我不经常写Python;我在业余时间写Ruby来上班,并写Clojure,但我确实喜欢Python,并且对Python有一些经验。我欢迎有关如何编写更多“ Pythonic”代码,更简单的代码或接口或如何使代码更强大的建议。理想情况下,我希望它“正常工作”并能够接收甚至格式错误的数据。不幸的是,我认为我需要在命令行中将
msg
参数保留在引号中,否则shell会将单点或双点解释为当前目录或父目录。我正在考虑使用Boyer-Moore算法而不是查找表,但我不确定是否值得。
import re
import argparse
from typing import Dict
eng = {
"a" : ".-",
"b" : "-...",
"c" : "-.-.",
"d" : "-..",
"e" : ".",
"f" : "..-.",
"g" : "--.",
"h" : "....",
"i" : "..",
"j" : ".---",
"k" : "-.-",
"l" : ".-..",
"m" : "--",
"n" : "-.",
"o" : "---",
"p" : ".--.",
"q" : "--.-",
"r" : ".-.",
"s" : "...",
"t" : "-",
"u" : "..-",
"v" : "...-",
"w" : ".--",
"x" : "-..-",
"y" : "-.--",
"z" : "--..",
" " : "/",
"0" : "-----",
"1" : ".----",
"2" : "..---",
"3" : "...--",
"4" : "....-",
"5" : ".....",
"6" : "-....",
"7" : "--...",
"8" : "---..",
"9" : "----.",
"," : ",",
"." : ".",
"!" : "!",
"?" : "?",
} # type: Dict[str, str]
morse = {v: k for k, v in eng.items()} # type: Dict[str, str]
def morsep(msg: str) -> bool:
if msg[0][0] in ['.', '-', '/']:
return True
else:
return False
def morse_to_eng(msg: str) -> str:
out = "" # type: str
split_msg = re.split(" ", msg) # type: list
filtered_msg = [e for e in split_msg if e] # type: list
for char in filtered_msg:
c = morse[char] # type: str
out += c
return("".join(out))
def eng_to_morse(msg: str) -> str:
out = "" # type: str
for char in msg:
c = eng[char] # type: str
out += "{} ".format(c)
return("".join(out))
def decode(msg: str) -> str:
"Main control flow."
if morsep(msg) == True:
return(morse_to_eng(msg))
else:
return(eng_to_morse(msg))
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Translate English to Morse code, and vice versa.')
parser.add_argument('-v', '--version', help='Show the version.', action='version', version='Morse 0.1')
parser.add_argument('msg', type=str, nargs=1,
help='The message to be decoded. Input type will be automatically detected and converted. \
Must be wrapped in quotes.')
args = parser.parse_args()
out = decode(args.msg[0]) # type: str
print("{}".format(out))
#1 楼
总体而言,此代码非常简单且易于遵循。我只是指出了一些建议。函数语法
def func_name(param_name: type) -> return_type:
是Python 3中的新功能。但是,在Python中使用它并不是很常见的事情,而且我认为它看起来不是非常pythonic。
您的代码在不创建此类函数的情况下也可以正常工作,因此我建议您坚持使用通常的语法:
def func_name(param_name):
这个笨拙的声明:
if msg[0][0] in ['.', '-', '/']:
return True
else:
return False
可以简化为更Python化和更干净的版本:
return msg[0][0] in ['.', '-', '/']
类似的评论:
# type: list
确实没有必要,只需在代码中添加噪音即可。只需阅读代码,审查它的人就应该能够确定每个变量的类型。
您需要进行更多的错误捕获。
例如,假设您要将莫尔斯电码的字符串翻译成英语。如果您遇到的字符不是有效的摩尔斯字符怎么办?您的程序将在此处引发错误:
for char in msg:
c = eng[char] # <======
out += "{} ".format(c)
因此,这是您应该执行的操作:
一个
try/except
。在
except
中,抛出一个自定义的InvalidMorseLetter
异常。退出
我的意思是:
try:
c = eng[char] # type: str
except KeyError:
raise(InvalidMorseLetter)
<
其中
InvalidMorseLetter
是:class InvalidMorseLetter(Exception):
pass
在这里和这里阅读。
在代码中,我写了一个
KeyError
,因为那是您应该使用一个自定义异常,因为它专门描述您的特定代码出了什么问题,而不仅仅是一般的
KeyError
。将英语翻译为莫尔斯电码时,应该做与此类似的事情。
感谢Zenohm的帮助。
翻译功能,您不应该在每次迭代中不断修改单个字符串:
c = morse[char] # type: str
out += c # <======================
原因:python字符串是不可变的。因此,通过不断更改字符串,实际上您每次都在创建一个新字符串。这是非常低效的。
如Zenohm在评论中所述,您应该按照以下方式进行操作:
return ''.join("{} ".format(eng[char]) for char in msg))
尽管修改单个字符串并没有什么坏习惯,并且
在这里并不是真正的问题,但我认为,如果他开始避免马上修改不可变对象,那会很好。蝙蝠。
返回''.join(“ {}” .format(eng [char])for msg中的char)可以用于
代替他的原始字符串修改,这将有助于
/>鼓励将来更好地实践。
评论
\ $ \ begingroup \ $
谢谢!我做了您在git repo中建议的更改。我包括类型注释和注释,因为我使用的是mypy。我试图学习更好,更明确地使用类型,因此(希望)在学习Haskell时会更容易。因此,我暂时将其保留。
\ $ \ endgroup \ $
– bsima
15年7月13日在1:38
\ $ \ begingroup \ $
完成!但是,您的意思是除了在最后两个代码块中捕获而不是捕获?
\ $ \ endgroup \ $
– bsima
15年7月13日在2:09
\ $ \ begingroup \ $
@BenSima啊,是的!抱歉,在编写答案时,我非常努力地忘记了这一点。我已经修复了。
\ $ \ endgroup \ $
– SirPython
15年7月13日在2:13
\ $ \ begingroup \ $
@BenSima mypy仅从函数定义中推断类型,您可以删除注释类型。
\ $ \ endgroup \ $
– Caridorc
15年7月13日在11:26
\ $ \ begingroup \ $
@SirPython虽然修改单个字符串并不是一个坏习惯,而且在这里并不是真正的问题,但我认为,如果他立即避免修改不可变对象,那将是很好的。返回''.join(“ {}” .format(eng [char])for msg中的char)可以代替他原来的字符串修改,并且将来会鼓励更好的实践。
\ $ \ endgroup \ $
–千欧姆
15年7月13日在15:26