簡體   English   中英

Python中的功能與命令式風格

[英]Functional vs. imperative style in Python

我最近花了一些業余時間試圖圍繞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()方法,但是當我執行這個轉換時我意識到這一點,所以我在示例中就這樣離開了。)

我的問題是:盡管如此,代碼的后一版本是否比前者更具可讀性 與前一版本相比,它似乎是一個更加單一的表達方式,與之前的版本相比,你有機會從更小,更原子的部分構建塊的含義。 這個問題來自於我試圖解碼所謂的易於理解的Haskell函數,以及我作為一年級CS學生的TA的堅持,我們編寫代碼的主要原因之一(經常被忽視)是溝通與其他程序員/計算機科學家的想法 我很緊張,terser風格是只寫代碼,因此違背了溝通和理解代碼的目的。

我的問題是:盡管如此,代碼的后一版本是否比前者更具可讀性? 這似乎是一個更加整體的表達,必須同時被一個人弄清楚

我會說它更具可讀性,但不一定是最具可讀性的選擇。 是的,它在一條線上更具邏輯性,但這被三個事實所抵消。

首先,您仍然可以精神上將其分解為更小的部分,並在組合它們之前單獨理解它們。 我立即看到你在總結一些東西 (在這個階段我不需要知道你在總結什么 )。 我還看到你從每個letter scoretable表中得到條目,如果不存在則默認為0(在這個階段我不必知道這個列表會發生什么)。 這些東西可以獨立識別和理解。 其次,很少有一些獨立的部分,可能是兩個或三個。 立即理解這並不是不合理的,當幾十個問題彼此相鄰時,“單片”方面更成問題。

最后,第一個版本的假設優勢,

與之前的版本相比,您有機會從更小,更原子的部分構建塊的含義。

也是一個問題:當我開始閱讀時,我看到一個for循環。 這很好,但它實際上並沒有告訴我任何東西(除了有一個循環,這不能幫助我理解邏輯,只有它的實現)。 所以我必須記住這個事實並繼續閱讀以后解決這個循環的含義 在某種程度上,任何代碼都是如此,但是代碼越多,代價越大。 同樣地, score = 0線本身並不意味着什么,它只是一個很小的實現細節,沒有人需要知道這個函數通過將每個單詞的字母的分數相加來計算單詞的拼字比分。

在閱讀命令性循環時,必須跟蹤多個可變變量,控制流程等,以確定發生了什么,並且必須將這些部分拼湊在一起。 此外,它只是閱讀更多的字符,因此即使理解在任何情況下都是即時的,理解也需要更長的時間。 您必須考慮這些成本。 無論通過讓每條線更簡單而獲得什么,都會失去這種效果。

也就是說,以下版本可以說更清晰,正是因為它將算法的兩個部分分成不同的部分:

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

但差異相當小,相當主觀。 兩者都很好,比你的第一個版本要好得多。 (哦,另一件事:我使用生成器表達而不是列表理解,我只保持列表理解以最小化噪聲。)

這些東西主要是品味問題。 應該記住,品味本身就是教育和經驗的問題 - 你會發現更長,更具可見性的代碼更具可讀性,因為這是你學會閱讀的唯一內容(到目前為止)。

我發現你的第二種形式更具可讀性,因為我習慣了功能風格的形式,並且我理解其中的所有元素。 我經常發現簡潔的haskell代碼難以辨認,因為我還沒有學習所有的運算符。

在我看來,實際的解決方案是:(a)使用注釋(b)避免任何過於聰明的事情(c)解釋你選擇做的任何聰明的事情(d)簡潔和不縮進通常比大量和深刻的縮進更容易閱讀; (e)記住你的觀眾。

將這些原則應用於這種情況:在python中,您可以期望通過簡單的功能操作表達的事物以這種方式表達,因此您的受眾應該對此感到滿意。 在任何情況下,您的代碼都需要注釋來解釋您是否(或不)打算默默地忽略無效(未標記)字符。

我認為簡潔的風格是很好的,因為你可以在這種情況下自由擴展它,而不會在控制結構上浪費大量的垂直空間,就像第一個中的if一樣。 例如

def scrabble_score(word, scoretable):
    # local function to look up a score in the table
    def get_score(x): return scoretable.get(x,0)

    scores = map(get_score, word)  # convert word into a list of scores

    return sum(scores)

我發現它最具可讀性,即使它需要更多行。 我認為這是陳述式的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM