成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

可愛的Python函數(shù)式編程(三)

開發(fā) 后端
作者David Mertz在其文章《可愛的Python:“Python中的函數(shù)式編程”》中的第一部分和第二部分中觸及了函數(shù)式編程的大量基本概念。本文中他將繼續(xù)前面的討論,解釋函數(shù)式編程的其它功能。

摘要:作者David Mertz在其文章《可愛的Python:“Python中的函數(shù)式編程”》中的第一部分第二部分中觸及了函數(shù)式編程的大量基本概念。本文中他將繼續(xù)前面的討論,解釋函數(shù)式編程的其它功能,如currying和Xoltar Toolkit中的其它一些高階函數(shù)。

表達式綁定

有一位從不滿足于解決部分問題讀者,名叫Richard Davies,提出了一個問題,問是否可以將所有的綁定全部都轉(zhuǎn)移到一個單個的表達式之中。首先讓我們簡單看看,我們?yōu)槭裁聪脒@么做,然后再看看由comp.lang.python中的一位朋友提供的一種異常優(yōu)雅地寫表達式的方式。

讓我們回想一下功能模塊的綁定類。使用該類的特性,我們可以確認(rèn)在一個給定的范圍塊內(nèi),一個特定的名字僅僅代表了一個唯一的事物。

具有重新綁定向?qū)У?Python 函數(shù)式編程(FP) 

  1. >>> from functional import *  
  2. >>> let = Bindings()  
  3. >>> let.car = lambda lst: lst[0]  
  4. >>> let.car = lambda lst: lst[2]  
  5. Traceback (innermost last):  
  6.   File "<stdin>", line 1in ?  
  7.   File "d:\tools\functional.py", line 976in __setattr__  
  8.      
  9. raise BindingError, "Binding '%s' cannot be modified." % name  
  10. functional.BindingError:  Binding 'car' cannot be modified.  
  11. >>> let.car(range(10))  
  12. 0 

綁定類在一個模塊或者一個功能定義范圍內(nèi)做這些我們希望的事情,但是沒有辦法在一條表達式內(nèi)使之工作。然而在ML家族語言(譯者注:ML是一種通用的函數(shù)式編程語言),在一條表達式內(nèi)創(chuàng)建綁定是很自然的事。

Haskell 命名綁定表達式

  1. -- car (x:xs) = x  -- *could* create module-level binding  
  2. list_of_list = [[1,2,3],[4,5,6],[7,8,9]]  
  3.  
  4. -- 'where' clause for expression-level binding  
  5. firsts1 = [car x | x <- list_of_list] where car (x:xs) = x  
  6.  
  7. -- 'let' clause for expression-level binding  
  8. firsts2 = let car (x:xs) = x in [car x | x <- list_of_list]  
  9.  
  10. -- more idiomatic higher-order 'map' technique  
  11. firsts3 = map car list_of_list where car (x:xs) = x  
  12.  
  13. -- Result: firsts1 == firsts2 == firsts3 == [1,4,7

Greg Ewing 發(fā)現(xiàn)用Python的list概念實現(xiàn)同樣的效果是有可能的;甚至我們可以用幾乎與Haskell語法一樣干凈的方式做到。

Python 2.0+ 命名綁定表達式

  1. >>> list_of_list = [[1,2,3],[4,5,6],[7,8,9]]  
  2. >>> [car_x for x in list_of_list for car_x in 
  3.  (x[0],)]  
  4. [147

在列表解析(list comprehension)中將表達式放入一個單項元素(a single-item tuple)中的這個小技巧,并不能為使用帶有表達式級綁定的高階函數(shù)提供任何思路。要使用這樣的高階函數(shù),還是需要使用塊級(block-level)綁定,就象以下所示:

Python中的使用塊級綁定的'map()'

  1. >>> list_of_list = [[1,2,3],[4,5,6],[7,8,9]]  
  2. >>> let = Bindings()  
  3. >>> let.car = lambda l: l[0]  
  4. >>> map(let.car,list_of_list)  
  5. [147

這樣真不錯,但如果我們想使用函數(shù)map(),那么其中的綁定范圍可能會比我們想要的更寬一些。然而,我們可以做到的,哄騙列表解析讓它替我們做名字綁定,即使其中的列表并不是我們最終想要得到的列表的情況下也沒問題:

從Python的列表解析中“走下舞臺” 

  1. # Compare Haskell expression:  
  2. # result = func car_car  
  3. #          where  
  4. #              car (x:xs) = x  
  5. #              car_car = car (car list_of_list)  
  6. #              func x = x + x^2  
  7. >>> [func for x in list_of_list  
  8. ...         
  9. for car in (x[0],)  
  10. ...         
  11. for func in (car+car**2,)][0]  
  12. 2 

我們對list_of_list列表中第一個元素的第一個元素進行了一次算數(shù)運算,而且期間還對該算術(shù)運算進行了命名(但其作用域僅僅是在表達式的范圍內(nèi))。作為一種“優(yōu)化”,我們可以不用費心創(chuàng)建多于一個元素的列表就能開始運算了,因為我們結(jié)尾處用的索引為0,所以我們僅僅選擇的是第一個元素。:

從列表解析中高效地走下舞臺

  1. >>> [func for x in list_of_list[:1]  
  2. ...       for car in (x[0],)  
  3. ...       for func in (car+car**2,)][0]  
  4. 2 

高階函數(shù):currying

Python內(nèi)建的三個最常用的高階函數(shù)是:map()、reduce()和filter()。這三個函數(shù)所做的事情 —— 以及謂之為“高階”(higher-order)的原因 —— 是接受其它函數(shù)作為它們的(部分)參數(shù)。還有別的一些不屬于內(nèi)置的高階函數(shù),還會返回函數(shù)對象。

藉由函數(shù)對象在Python中具有首要地位, Python一直都有能讓其使用者構(gòu)造自己的高階函數(shù)的能力。舉個如下所示的小例子:

Python中一個簡單函數(shù)工廠(function factory)

  1. >>> def 
  2.  foo_factory():  
  3. ...      
  4. def 
  5.  foo():  
  6. ...          
  7. print   
  8. "Foo function from factory" 
  9. ...      
  10. return foo  
  11. ...  
  12. >>> f = foo_factory()  
  13. >>> f()  
  14. Foo function from factory 

本系列文章的第二部分我討論過的Xoltar Toolkit中,有一組非常好用的高階函數(shù)。Xoltar的functional模塊中提供的絕大多數(shù)高階函數(shù)都是在其它各種不同的傳統(tǒng)型函數(shù)式編程語言中發(fā)展出來的高階函數(shù),其有用性已經(jīng)過多年的實踐驗證。

可能其中最著名、最有用和最重要的高階函數(shù)要數(shù)curry()了。函數(shù)curry()的名字取自于邏輯學(xué)家Haskell Curry,前文提及的一種編程語言也是用他姓名當(dāng)中的名字部分命名的。"currying"背后隱含的意思是,(幾乎)每一個函數(shù)都可以視為只帶一個參數(shù)的部分函數(shù)(partial function)。要使currying能夠用起來所需要做的就是讓函數(shù)本身的返回值也是個函數(shù),只不過所返回的函數(shù)“縮小了范圍”或者是“更加接近完整的函數(shù)”。這和我在第二部分中提到的閉包特別相似 —— 對經(jīng)過curry后的返回的后繼函數(shù)進行調(diào)用時一步一步“填入”最后計算所需的更多數(shù)據(jù)(附加到一個過程(procedure)之上的數(shù)據(jù))

現(xiàn)在讓我們先用Haskell中一個很簡單例子對curry進行講解,然后在Python中使用functional模塊重復(fù)展示一下這個簡單的例子:

在Haskell計算中使用Curry

  1. computation a b c d = (a + b^2+ c^3 + d^4)  
  2. check = 1 + 2^2 + 3^3 + 5^4 
  3. fillOne   = computation 1   
  4. -- specify "a" 
  5. fillTwo   = fillOne 2       
  6. -- specify "b" 
  7. fillThree = fillTwo 3       
  8. -- specify "c" 
  9. answer    = fillThree 5     
  10. -- specify "d" 
  11. -- Result: check == answer == 657 

現(xiàn)在使用Python:

在Python計算中使用Curry

  1. >>> from functional import curry  
  2. >>> computation = lambda a,b,c,d: (a + b**2 + c**3 + d**4)  
  3. >>> computation(1,2,3,5)  
  4. 657 
  5. >>> fillZero  = curry(computation)  
  6. >>> fillOne   = fillZero(1)    
  7. # specify "a"  
  8. >>> fillTwo   = fillOne(2)     
  9. # specify "b"  
  10. >>> fillThree = fillTwo(3)     
  11. # specify "c"  
  12. >>> answer    = fillThree(5)   
  13. # specify "d"  
  14. >>> answer  
  15. 657 

第二部分中提到過的一個簡單的計稅程序的例子,當(dāng)時用的是閉包(這次使用curry()),可以用來進一步做個對比:

Python中curry后的計稅程序

  1. from functional import *  
  2.  
  3. taxcalc = lambda income,rate,deduct: (income-(deduct))*rate  
  4. taxCurry = curry(taxcalc)  
  5. taxCurry = taxCurry(50000)  
  6. taxCurry = taxCurry(0.30)  
  7. taxCurry = taxCurry(10000)  
  8. print "Curried taxes due =",taxCurry  
  9.  
  10. print "Curried expression taxes due =", \  
  11.       curry(taxcalc)(50000)(0.30)(10000

和使用閉包不同,我們需要以特定的順序(從左到右)對參數(shù)進行curry處理。當(dāng)要注意的是,functional模塊中還包含一個rcurry()類,能夠以相反的方向進行curry處理(從右到左)。

從一個層面講,其中的第二個print語句同簡單的同普通的taxcalc(50000,0.30,10000)函數(shù)調(diào)用相比只是個微小的拼寫方面的變化。但從另一個不同的層面講,它清晰地一個概念,那就是,每個函數(shù)都可以變換成僅僅帶有一個參數(shù)的函數(shù),這對于剛剛接觸這個概念的人來講,會有一種特別驚奇的感覺。

其它高階函數(shù)

除了上述的curry功能,functional模塊簡直就是一個很有意思的高階函數(shù)萬能口袋。此外,無論用還是不用functional模塊,編寫你自己的高階函數(shù)真的并不難。至少functional模塊中的那些高階函數(shù)為你提供了一些很值一看的思路。

它里面的其它高階函數(shù)在很大程度上感覺有點象是“增強”版本的標(biāo)準(zhǔn)高階函數(shù)map()、filter()和reduce()。這些函數(shù)的工作模式通常大致如此:將一個或多個函數(shù)以及一些列表作為參數(shù)接收進來,然后對這些列表參數(shù)運行它前面所接收到的函數(shù)。在這種工作模式方面,有非常大量很有意思也很有用的擺弄方法。還有一種模式是:拿到一組函數(shù)后,將這組函數(shù)的功能組合起來創(chuàng)建一個新函數(shù)。這種模式同樣也有大量的變化形式。下面讓我們看看functional模塊里到底還有哪些其它的高階函數(shù)。

sequential()和also()這兩個函數(shù)都是在一系列成分函數(shù)(component function)的基礎(chǔ)上創(chuàng)建一個新函數(shù)。然后這些成分函數(shù)可以通過使用相同的參數(shù)進行調(diào)用。兩者的主要區(qū)別就在于,sequential()需要一個單個的函數(shù)列表作為參數(shù),而also()接受的是一系列的多個參數(shù)。在多數(shù)情況下,對于函數(shù)的副作用而已這些會很有用,只是sequential()可以讓你隨意選擇將哪個函數(shù)的返回值作為組合起來后的新函數(shù)的返回值。

順序調(diào)用一系列函數(shù)(使用相同的參數(shù))

  1. >>> def a(x):  
  2. ...     print x,  
  3. ...     return "a" 
  4. ...  
  5. >>> def b(x):  
  6. ...     print x*2,  
  7. ...     return "b" 
  8. ...  
  9. >>> def c(x):  
  10. ...     print x*3,  
  11. ...     return "c" 
  12. ...  
  13. >>> r = also(a,b,c)  
  14. >>> r  
  15. <functional.sequential instance at 0xb86ac>  
  16. >>> r(5)  
  17. 5 10 15 
  18. 'a' 
  19. >>> sequential([a,b,c],main=c)('x')  
  20. x xx xxx  
  21. 'c' 

isjoin()和conjoin()這兩個函數(shù)同equential()和also()在創(chuàng)建新函數(shù)并對參數(shù)進行多個成分函數(shù)的調(diào)用方面非常相似。只是disjoin()函數(shù)用來查詢成分函數(shù)中是否有一個函數(shù)的返回值(針對給定的參數(shù))為真;conjoin()函數(shù)用來查詢是否所有的成分函數(shù)的返回值都為真。在這些函數(shù)中只要條件允許就會使用邏輯短路,因此disjoin()函數(shù)可能不會出現(xiàn)某些副作用。joinfuncs()i同also()類似,但它返回的是由所有成分函數(shù)的返回值組成的一個元組(tuple),而不是選中的某個主函數(shù)。

前文所述的幾個函數(shù)讓你可以使用相同的參數(shù)對一系列函數(shù)進行調(diào)用,而any()、all()和 none_of()這三個讓你可以使用一個參數(shù)列表對同一個函數(shù)進行多次調(diào)用。在大的結(jié)構(gòu)方面,這些函數(shù)同內(nèi)置的map()、reduce()和filter()有點象。 但funtional模塊中的這三個高階函數(shù)中都是對一組返回值進行布爾(boolean)運算得到其返回值的。例如:

對一系列返回值的真、假情況進行判斷

  1. >>> from functional import *  
  2. >>> isEven = lambda n: (n%2 == 0)  
  3. >>> any([1,3,5,8], isEven)  
  4. 1 
  5. >>> any([1,3,5,7], isEven)  
  6. 0 
  7. >>> none_of([1,3,5,7], isEven)  
  8. 1 
  9. >>> all([2,4,6,8], isEven)  
  10. 1 
  11. >>> all([2,4,6,7], isEven)  
  12. 0 

有點數(shù)學(xué)基礎(chǔ)的人會對這個高階函數(shù)非常感興趣:iscompose(). 將多個函數(shù)進行合成(compostion)指的是,將一個函數(shù)的返回值同下個函數(shù)的輸入“鏈接到一起”。對多個函數(shù)進行合成的程序員需要負責(zé)保證函數(shù)間的輸入和輸出是相互匹配的,不過這個條件無論是程序員在何時想使用返回值時都是需要滿足的。舉個簡單的例子和闡明這一點:

創(chuàng)建合成函數(shù)

  1. >>> def minus7(n): return n-7 
  2. ...  
  3. >>> def times3(n): return n*3 
  4. ...  
  5. >>> minus7(10)  
  6. 3 
  7. >>> minustimes = compose(times3,minus7)  
  8. >>> minustimes(10)  
  9. 9 
  10. >>> times3(minus7(10))  
  11. 9 
  12. >>> timesminus = compose(minus7,times3)  
  13. >>> timesminus(10)  
  14. 23 
  15. >>> minus7(times3(10))  
  16. 23 

后會有期

衷心希望我對高階函數(shù)的思考能夠引起讀者的興趣。無論如何,請動手試一試。試著編寫一些你自己的高階函數(shù);一些可能很有用,很強大。告訴我它如何運行;或許這個系列之后的章節(jié)會討論讀者不斷提供的新觀點,新想法。

原文鏈接:http://www.oschina.net/translate/python-functional-programming-part3

責(zé)任編輯:張偉 來源: oschina
相關(guān)推薦

2013-03-04 10:03:17

Python函數(shù)式編程

2013-03-04 09:47:08

Python函數(shù)式編程

2023-12-14 15:31:43

函數(shù)式編程python編程

2013-09-09 09:41:34

2022-07-07 09:03:36

Python返回函數(shù)匿名函數(shù)

2012-09-21 09:21:44

函數(shù)式編程函數(shù)式語言編程

2018-11-15 10:20:59

Python函數(shù)式編程編程語言

2022-10-31 08:02:07

Python函數(shù)式編程

2024-02-28 07:59:25

2019-01-17 10:25:56

Python編程語言程序員

2024-09-11 16:30:55

Python函數(shù)編程

2016-10-31 20:46:22

函數(shù)式編程Javascript

2011-03-08 15:47:32

函數(shù)式編程

2020-09-24 10:57:12

編程函數(shù)式前端

2025-03-11 10:00:20

Golang編程函數(shù)

2024-02-28 08:37:28

Lambda表達式Java函數(shù)式接口

2011-08-24 09:13:40

編程

2022-09-22 08:19:26

WebFlux函數(shù)式編程

2017-03-22 11:22:04

JavaScript函數(shù)式編程

2024-04-02 08:00:00

函數(shù)式編程開發(fā)
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 成人av免费 | 亚洲天堂日韩精品 | 日本精品一区二区 | 久久一区二区精品 | 久久天天综合 | 欧美成年人网站 | 日韩久久综合网 | 2018天天干天天操 | 亚洲伊人a | 国产一区二区三区欧美 | 国产免费一区二区三区 | 欧美xxxx色视频在线观看免费 | 夜夜爽99久久国产综合精品女不卡 | 精品影院 | 日韩av在线播 | 91人人看| 五月婷婷导航 | 欧美成人二区 | 91精品久久久久久久久久入口 | 亚洲v日韩v综合v精品v | 国产美女在线播放 | 草樱av | 亚洲精品久久嫩草网站秘色 | 精品视频在线播放 | 91成人免费 | 99国产在线 | 亚洲一区在线播放 | 日本黄视频在线观看 | 午夜小视频在线播放 | 久久三级av| 免费看国产精品视频 | 日韩成人中文字幕 | 中文字幕免费 | 91精品国产91久久久久福利 | 欧美国产精品久久久 | 91一区二区三区在线观看 | 黄色日本视频 | 一区二区三区四区不卡视频 | 殴美成人在线视频 | 二区在线视频 | 国产精品久久久久久久久久99 |