當前位置:編程學習大全網 - 編程語言 - Python和lisp在函數式編程上有哪些異同

Python和lisp在函數式編程上有哪些異同

Python內在的函數式功能

自Python 1.0起,Python就已具有了以上所列中的絕大多數特點。但是就象Python所具有的大多數特性壹樣,這些特點出現在了壹種混合了各種特性的語言 中。?和Python的OOP(面向對象編程) 特性非常象,妳想用多少就用多少,剩下的都可以不管(直到妳隨後需要用到它們為止)。在Python 2.0中,加入了列表解析(list comprehensions)這個非常好用的”語法糖“。 盡管列表解析沒有添加什麽新功能,但它讓很多舊功能看起來好了不少。

Python中函數式編程的基本要素包括functionsmap()、reduce()、filter()和lambda算子(operator)。 在Python 1.x中,apply()函數也可以非常方便地拿來將壹個函數的列表返回值直接用於另外壹個函數。Python 2.0為此提供了壹個改進後的語法。可能有點讓人驚奇,使用如此之少的函數(以及基本的算子)幾乎就足以寫出任何Python程序了;更加特別的是,幾乎 用不著什麽執行流程控制語句。

所有(if,elif,else,assert,try,except,finally,for,break,continue,while,def)這 些都都能通過僅僅使用函數式編程中的函數和算子就能以函數式編程的風格處理好。盡管真正地在程序中完全排除使用所有流程控制命令可能只在想參 加”Python混亂編程“大賽(可將Python代碼寫得跟Lisp代碼非常象)時才有意義,但這對理解函數式編程如何通過函數和遞歸表達流程控制很有 價值。

剔除流程控制語句

剔除練習首先要考慮的第壹件事是,實際上,Python會對布爾表達式求值進行“短路”處理。這就為我們提供了壹個if/elif/else分支語句的表達式版(假設每個分支只調用壹個函數,不是這種情況時也很容易組織成重新安排成這種情況)。 這裏給出怎麽做:

對Python中的條件調用進行短路處理

Python

# Normal statement-based flow control

if <cond1>:? func1()

elif <cond2>: func2()

else: func3()

# Equivalent "short circuit" expression

(<cond1> and func1()) or (<cond2> and func2()) or (func3())

# Example "short circuit" expression

>>> x = 3

>>> def pr(s): return s

>>> (x==1 and pr('one')) or (x==2 and pr('two')) or (pr('other'))

'other'

>>> x = 2

>>> (x==1 and pr('one')) or (x==2 and pr('two')) or (pr('other'))

'two'

我們的表達式版本的條件調用看上去可能不算什麽,更象是個小把戲;然而,如果我們註意到lambda算子必須返回壹個表達式,這就更值得關註了。既然如我 們所示,表達式能夠通過短路包含壹個條件判斷,那麽,lambda表達式就是個完全通用的表達條件判斷返回值的手段了。我們來壹個例子:

Python中短路的Lambda

Python

>>> pr = lambda s:s

>>> namenum = lambda x: (x==1 and pr("one")) \

....?or (x==2 and pr("two")) \

....?or (pr("other"))

>>> namenum(1)

'one'

>>> namenum(2)

'two'

>>> namenum(3)

'other'

將函數作為具有首要地位的對象

前面的例子已經表明了Python中函數具有首要地位,但有點委婉。當我們用lambda操作創建壹個函數對象時, 我們所得到的東西是完全通用的。就其本質而言,我們可以將我們的對象同名字”pr”和”namenum”綁定到壹起, 以完全相同的方式,我們也也完全可以將數字23或者字符串”spam” 同這些名字綁定到壹起。但是,就象我們可以無需將其綁定到任何名字之上就能直接使用數字23(也就是說,它可以用作函數的參數)壹樣,我們也可以直接使用 我們使用lambda創建的函數對象,而無需將其綁定到任何名字之上。在Python中,函數就是另外壹種我們能夠就像某種處理的值。

我們對具有首要地位的對象做的比較多的事情就是,將它們作為參數傳遞給函數式編程固有的函數map()、reduce()和filter()。這三個函數接受的第壹個參數都是壹個函數對象。

map()針對指定給它的壹個或多個列表中每壹項對應的內容,執行壹次作為參數傳遞給它的那個函數 ,最後返回壹個結果列表。

reduce()針對每個後繼項以及最後結果的累積結果,執行壹次作為參數傳遞給它的那個函數;例如,reduce(lambda n,m:n*m, range(1,10))是求”10的階乘”的意思(換言之,將每壹項和前面所得的乘積進行相乘)

filter()使用那個作為參數傳遞給它的函數,對壹個列表中的所有項進行”求值“,返回壹個由所有能夠通過那個函數測試的項組成的經過遴選後的列表。

我們經常也會把函數對象傳遞給我們自己定義的函數,不過壹般情況下這些自定義的函數就是前文提及的內建函數的某種形式的組合。

通過組合使用這三種函數式編程內建的函數, 能夠實現範圍驚人的“執行流程”操作(全都不用語句,僅僅使用表達式實現)。

  • 上一篇:帖子中的MFC是什麽意思
  • 下一篇:學期個人工作計劃
  • copyright 2024編程學習大全網