python - Python 中的函数式与命令式风格

标签 python python-2.7 coding-style functional-programming

我最近一直在花一些空闲时间来研究 Haskell 和一般的函数式编程。我的主要疑虑之一是(并将继续是)我认为简洁的函数式表达式(无论是 Haskell 还是任何其他语言)的不可读性。

这是一个例子。我只是在一些工作代码中进行了以下转换:

def scrabble_score(word, scoretable):    
    score = 0
    for letter in word:
        if letter in scoretable:
            score += scoretable[letter]
    return score

def scrabble_score(word, scoretable):
    return sum([scoretable.get(x, 0) for x in word])

后者写起来更令人满意(而且,请记住,我自己就是写它的人,阅读也是如此)。它更短更甜美,并且没有声明任何讨厌的变量,如果我在输入代码时犯了任何错误,这些变量可能会让人头疼。 (顺便说一句,我意识到我可以在命令式函数中使用 dict 的 get() 方法,但我在执行此转换时意识到了这一点,所以我在示例中保留了它。)

我的问题是:尽管如此,后一版本的代码真的比前一版本更具可读性吗?与以前的版本相比,这似乎是一个更单一的表达式,必须一次全部理解,在以前的版本中,您有机会从更小、更原子的部分构建 block 的含义。这个问题来自于我对尝试解码据称易于理解的 Haskell 函数感到沮丧,以及我作为一年级 CS 学生的助教坚持认为我们编写代码(经常被忽视)的主要原因之一是 < strong>与其他程序员/计算机科学家交流想法。我很担心这种简洁的风格有只写代码的味道,因此违背了交流和理解代码的目的。

最佳答案

My question is: despite all that, is the latter version of the code really more readable than the former? It seems like a more monolithic expression that has to be grokked all at once

我会说它更具可读性,但不一定是可读的选项。是的,这在一行中更合乎逻辑,但这被三个事实压倒了。

首先,您可以仍然在头脑中将它分解成更小的部分,并在组合它们之前分别理解它们。我立即看到您正在总结某事(在这个阶段我不必知道什么您正在总结)。我还看到您从 scoretable 中获取每个 letter 的条目,如果不存在则默认为 0(在这个阶段我不必知道接下来会发生什么列表)。这些东西是可以独立识别和理解的。 其次,有些独立的部分很少,可能只有两三个。立即理解这并非不合理,当数十个关注点并排放置时,“整体”方面更成问题。

最后,第一个版本的优点,

compared to the former version, where you have a chance to build up the meaning of the block from the smaller, more atomic pieces.

也是一个问题:当我开始阅读时,我看到一个 for 循环。这很好,但它实际上并没有告诉我任何东西(除了有一个循环,它不能帮助我理解逻辑,只能帮助我理解它的实现)。所以我必须牢记这个事实并继续阅读以解决这个循环意味着的问题。在某种程度上,这对任何代码都是正确的,但代码越多,情况就越糟。同样,score = 0 行本身意味着任何东西,它只是一个微小的实现细节,没有人需要知道它才能理解此函数计算单词的拼字游戏通过将单词的每个字母的分数相加来得分。

在阅读命令式循环时,必须跟踪多个可变变量、控制流等以弄清楚发生了什么,并且必须将各个部分拼凑在一起。再加上就是读的字多了,反正瞬间理解也需要更长的时间来理解。您必须考虑这些成本。无论您通过使每一行都更简单而可能获得的任何好处都会失去这种效果。

也就是说,以下版本可以说更清晰,正是因为它将算法的两个部分拆分为单独的行:

def scrabble_score(word, scoretable):
    letter_scores = [scoretable.get(letter, 0) for letter in word]
    return sum(letter_scores)

但差异相当小,这是相当主观的。两者都很好,比你的第一个版本好得多。 (哦,另一件事:我会使用生成器表达式而不是列表理解,我只保留列表理解以最小化噪音。)

关于python - Python 中的函数式与命令式风格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18345202/

相关文章:

python - 导入错误:没有名为 svmcmpl 的模块

Python heapify() 时间复杂度

python - Python中参数的强制命名

python - 检查两个变量是否具有来自两个不同集合的值,DRY 方式

javascript - jquery 滚动事件多次运行代码

python - 如何在 fastapi 中使用刷新 token ?

python - django 和多线程有任何已知问题吗?

python - 获取 zip 文件中包含的文件的文件列表

我的 PC 中的 Python 版本显示 2.7.17 而不是 3.8.5

python - 无法使用新数据点更新 Pyqtgraph 图