Ron*_*ury 7 python functional-programming coding-style python-2.7
我最近花了一些业余时间试图围绕Haskell和函数式编程.我的一个主要疑虑是(并且仍然是)我认为是简洁的,功能性的表达式(无论是在Haskell还是任何其他语言中)的不可读性.
这是一个例子.我刚刚在一些代码中进行了以下转换:
def scrabble_score(word, scoretable):
score = 0
for letter in word:
if letter in scoretable:
score += scoretable[letter]
return score
Run Code Online (Sandbox Code Playgroud)
至
def scrabble_score(word, scoretable):
return sum([scoretable.get(x, 0) for x in word])
Run Code Online (Sandbox Code Playgroud)
后者写作更令人满意(并且,请记住,我自己也是写作的人,也是读者).如果我在输入代码时犯了任何错误,它会更短更甜,并且不会声明任何令人头疼的变量.(顺便说一下,我意识到我可以get()
在命令式风格的函数中使用dict的方法,但我意识到它正在执行这个转换,所以我在示例中就这样离开了.)
我的问题是:尽管如此,代码的后一版本是否比前者更具可读性?与前一版本相比,它似乎是一个更加单一的表达方式,与之前的版本相比,你有机会从更小,更原子的部分构建块的意义.这个问题来自于我试图解码所谓的易于理解的Haskell函数,以及我作为一年级CS学生的TA的坚持,我们编写代码的主要原因之一(经常被忽视)是沟通与其他程序员/计算机科学家的想法.我很紧张,terser风格是只写代码,因此违背了沟通和理解代码的目的.
小智 6
我的问题是:尽管如此,代码的后一版本是否比前者更具可读性?这似乎是一个更加整体的表达,必须同时被一个人弄清楚
我会说它更具可读性,但不一定是最具可读性的选择.是的,它在一条线上更具逻辑性,但这被三个事实所抵消.
首先,您仍然可以在精神上将其分解为更小的部分,并在组合它们之前单独理解它们.我立即看到你在总结一些东西(在这个阶段我不需要知道你在总结什么).我还看到你从scoretable
每个中获取条目letter
,如果不存在则默认为0(在这个阶段我不必知道这个列表会发生什么).这些东西可以独立识别和理解.其次,很少有一些独立的部分,可能是两个或三个.立即理解这并不是不合理的,当几十个问题彼此相邻时,"单片"方面更成问题.
最后,第一个版本的假设优势,
与之前的版本相比,您有机会从更小,更原子的部分构建块的含义.
也是一个问题:当我开始阅读时,我看到一个for循环.这很好,但它实际上并没有告诉我任何东西(除了有一个循环,这不能帮助我理解逻辑,只有它的实现).所以我必须记住这个事实并继续阅读以后解决这个循环的含义.在某种程度上,任何代码都是如此,但是代码越多,代价越大.同样,这score = 0
条线本身并不代表任何东西,它只是一个很小的实现细节,没有人需要知道这个函数通过将每个单词的字母的分数相加来计算单词的拼字游戏分数.
在阅读命令性循环时,必须跟踪多个可变变量,控制流程等,以确定发生了什么,并且必须将这些部分拼凑在一起.此外,它只是阅读更多的字符,因此即使理解在任何情况下都是即时的,理解也需要更长的时间.您必须考虑这些成本.无论你通过让每条线更简单而获得什么,都会失去这种效果.
也就是说,以下版本可以说更清晰,正是因为它将算法的两个部分分成不同的部分:
def scrabble_score(word, scoretable):
letter_scores = [scoretable.get(letter, 0) for letter in word]
return sum(letter_scores)
Run Code Online (Sandbox Code Playgroud)
但差异相当小,相当主观.两者都很好,比你的第一个版本要好得多.(哦,另一件事:我使用生成器表达而不是列表理解,我只保持列表理解以最小化噪声.)
归档时间: |
|
查看次数: |
1242 次 |
最近记录: |