




版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
1、python良好編程習慣如果進行的是簡單的處理,請使用字符串方法,這樣可避免復雜的正則表達式所帶來的錯誤,并保證程序的可讀性。在原始字符串末尾使用反斜杠是語法錯誤。正則表達式的模式字符串中常常包含反斜杠字符。使用原始字符串來創(chuàng)建模式,可以避免對其中每個反斜杠進行轉(zhuǎn)義的必要,使模式字符串更容易理解。說明:原始字符串(rawstring),也就是在字符串之前加上字符前綴r后創(chuàng)建的一個字符串。通常,如果在字符串中出現(xiàn),python會把它視為轉(zhuǎn)義字符,并試圖用正確的轉(zhuǎn)義序列替換元字符及其后續(xù)字符。但是,如果元字符出現(xiàn)在一個原始字符串中,python不會把它解釋成轉(zhuǎn)義字符,而是將其視為字面意義的反斜杠字
2、符。例如,python會將n解釋成換行符,但將rn解釋成兩個字符-一個反斜杠和一個n。用函數(shù)式編程語言(比如說scheme)寫的程序可以反映出數(shù)學表達式的結構;數(shù)學表達式是由若干函數(shù)字符串組成的,其中的每一個都能計算出一個結果并且不產(chǎn)生任何副作用。同樣的函數(shù)用同樣的參數(shù)去調(diào)用就會產(chǎn)生同樣的結果,這和調(diào)用時的上下文是無關的。用這樣的方法可以將我們的代碼優(yōu)雅地結構化(并且一定程度上也起到了簡化的效果)。python編程語言擁有所有讓它在函數(shù)式編程(fp)上有優(yōu)勢的特性。在這篇文章中,我們將從“pythonic”的角度來看一下fp中的一些有趣的思想如高階函數(shù)、閉包、lambda以及柯里化等等。什么是
3、函數(shù)式編程?作為程序的一部分,我們所寫的函數(shù)只是在表面上和數(shù)學函數(shù)類似。比方說我們寫這么一個函數(shù):int current_balance = 100;int withdraw(int w)current_balance = current_balance - w;return current_balance;我們調(diào)用一次“withdraw(10)”之后90這個值將會被返回。再調(diào)用一次“withdraw(10)”則返回80。如果“withdraw”是一個“純”數(shù)學函數(shù)的話,那么兩次調(diào)用應該返回同樣的值,因為我們傳給它的參數(shù)值是一樣的。而我們的程序則“記住”了前次的調(diào)用(它有“狀態(tài)”)然后每次都返
4、回一個新的值 。一個如下的數(shù)學方程:y = f(a) + g(b) + f(a)有一個很好的屬性就是它可以被化簡為:y = 2*f(a) + g(b)事實上如果有一個計算機程序是由一組會修改全面變量的函數(shù)構成的話,我們是無法對它進行這樣化簡的。相比于生成一個數(shù)學證明,驗證一個計算機程序的正確性更像是一個探索各種假設分析的情境的過程?!百x值”操作符也帶來了些問題。讓我們簡單地看一個計算階乘的循環(huán):# compute factorial of nint f = 1, n = 5;while (n 0) f = f * n;n = n - 1;return f;我們會犯的一個常見的錯誤就是在循環(huán)體內(nèi)
5、交換兩個語句的順序。因為賦值操作符改變了它左邊的符號的值,所以這讓我們在考慮在我們的程序中每一個動作的順序時需要格外的小心。函數(shù)式編程的范式鼓勵我們把程序結構化成一系列“純”的函數(shù),這些函數(shù)沒有全局的狀態(tài)也不使用賦值操作符(注意這并不是所有情況下都可行的,很顯然一個銀行的系統(tǒng)就需要“記住”很多東西)。函數(shù)式編程人員使用遞歸的函數(shù)調(diào)用(循環(huán)可以當成一種特殊的遞歸,于是特定的循環(huán)結構“while”和“for”也就不需要了)來產(chǎn)生重復性的行為。函數(shù)則成為了我們的“一等公民”,比方說,它們可以被當成參數(shù)傳給另一個函數(shù),也可以被別的函數(shù)返回,這就促成了我們稱之為“高階函數(shù)”的產(chǎn)生。當和“閉包”這個思想結
6、合在一起的時候,這就成為了一個很強大的思想,它可以很簡單地捕獲很多復雜的可計算模式。遞歸表示python中定義一個遞歸函數(shù)沒什么了不起的。這里是一個用python寫的經(jīng)典階乘函數(shù):def fact(n):if (n = 0): return 1return n * fact(n - 1)作為一等公民對象的函數(shù)讓我們在python的命令行中定義兩個函數(shù),然后來做些實驗:def sqr(x): return x*x.def cube(x): return x*x*x.sqra = sqr, cubea0(2)def compose(f, g): return f(g(x).compose(sqr,
7、 cube, 2)64我們先將兩個函數(shù)存到數(shù)組中,然后用“a02”的方式來調(diào)用“sqr”。接著我們又定義一個叫“compose”的函數(shù),然后將“sqr”和“cube”這兩個函數(shù)作為參數(shù)傳給它們并進行調(diào)用。注意這邊并沒有任何特殊的記號,我們操作函數(shù)時就好像它們是像數(shù)組和數(shù)字之類的對象一樣。高階函數(shù)的威力structure and interpretation of computer programs,這本由abelson和sussman寫的傳奇般的“指南書”中詳細地描述了高階函數(shù)的作用。一個“函數(shù)”(或子程序、輔程序、過程)被認為是一種捕獲模式的機制。如果我們有如下形式的語句a*a*ab*b*b
8、c*c*c.我們可以想到要定義一個叫“cube”(立方)的函數(shù)來捕獲這種模式的本質(zhì)并給它一個名字。將函數(shù)當成參數(shù)傳給別的函數(shù)的這種能力拓寬了這種“模式捕獲”機制的領域。讓我們來看一個簡單的函數(shù),叫“sum”:def sum(a, b):if (a b): return 0else: return a + sum(a+1, b)這個函數(shù)將從“a”到“b”的所有數(shù)字進行累加。我們嘗試著拓寬這個函數(shù)的領域,讓它具有操作任意序列的能力,比如說:1/(1*3) + 1/(5*7) + 1/(9*11) + .我們發(fā)現(xiàn)到上面的序列和下面這個:1 + 2 + 3 + 4 + .有著相似之處,即它們都是“求和
9、”。我們想象一個變量“a”從1變到2,2變到3,然后一直這么做下去。這種從1到2的變化可以用一個函數(shù)來捕獲(就是一個簡單的“加1”函數(shù))。在第一個序列中,這個變量是從1到5,5到9,9到11這么變化的。所以在這里的這種變化我們可以用一個“加4”的函數(shù)來捕獲。另一個小問題是,這個數(shù)列中的通項并不是數(shù)字1、5、9、11等等而是1/(1*3)、1/(5*7)但是接著這種轉(zhuǎn)換也可以通過一個函數(shù)表示!我們觀察的結果可以用一個函數(shù)“sigma”表示出來:def sigma(term, a, next, b):if(a b): return 0return term(a) + sigma(term, nex
10、t(a), next, b)然后看看我們怎么通過“sigma”來計算這個序列的和:1/(1*3) + 1/(5*7) + 1/(9*11) + .我們來定義兩個函數(shù):def term(x): return 1.0/(x * (x+2)def next(x): return x + 4然后調(diào)用:sigma(term, 1, next, 1000)這樣就成功了!現(xiàn)在我們就能只要定義兩個輔助函數(shù)就可以累積任意數(shù)列的和了。故事還沒有結束。我們可以想想怎么將“sigma”進行泛化。我們注意到“sigma”只是使用了一個組合函數(shù)“add”來將一個序列中的各項“組合”起來。為什么不用一個泛化的過程來根據(jù)一個
11、用戶定義好并作為參數(shù)傳過來的函數(shù)來組合函數(shù)中的各項呢?讀者可以把這個當成一個練習來試試!使用“l(fā)ambda”我們再來試試下面些命令:lambda x: x+4function at 0x402ba25cf = lambda x: x+4f(3)7lambda關鍵字創(chuàng)建了一個匿名函數(shù)。lambda的主體只能由一些簡單的表達式組成。在上一個例子中,我們用lambda來創(chuàng)建一個函數(shù),這個函數(shù)接受一個參數(shù),并將它加4后返回。當我們需要定義一個函數(shù)而只將這個函數(shù)用于傳遞給另一個函數(shù)的時候,我們應當想到使用“l(fā)ambda”。比如說:map(lambda x:x*x, 1,3,7,9)1, 9, 49, 8
12、1filter(lambda x: x%2 = 0, range(10)0, 2, 4, 6, 8map函數(shù)接受一個函數(shù)和一個列表作為參數(shù),然后將函數(shù)運用在原列表的每一個元素上,并將得到的新列表返回。filter也是類似的,它返回的列表只由原列表中那些能使函數(shù)返回true的元素組成。閉包python允許嵌套的函數(shù)定義。def add(x):return lambda(y): x+y調(diào)用add(3)將返回一個帶單參數(shù)的函數(shù)?,F(xiàn)在這個返回的函數(shù)有一個特性它能記住它被創(chuàng)建時的環(huán)境。函數(shù)體中的“x”是我們在調(diào)用“add”時提供給它的。我們把這樣的函數(shù)叫作“閉包”。調(diào)用add(3)(4)將使這個函數(shù)以x
13、 = 3和y = 4的值執(zhí)行。也許你已經(jīng)注意到了一些有趣的地方。我們并沒有定義一個接受兩個參數(shù)的“add”函數(shù),而是可以將一個單參數(shù)的函數(shù)嵌在另一個單參數(shù)的函數(shù)中,并產(chǎn)生相同的效果。我們也可以將這升到任意層次:def add3(x):return lambda y: lambda z: x+y+z現(xiàn)在我們就可以調(diào)用“add3(1)(2)(3)”了!這個思想在fp社區(qū)中被稱為“柯里化”。讓我們試著寫一個做“數(shù)值”微分的函數(shù)。def differentiate(f):return lambda x: (f(x+0.001) - f(x)/0.001這個函數(shù)可以這么試出來:p = different
14、iate(cube)p(2)12用“cube”作為參數(shù)來調(diào)用differentiate會返回一個單參數(shù)函數(shù),這個函數(shù)會記得“f”的值等于“cube”?,F(xiàn)在,用2作為參數(shù)來調(diào)用這個函數(shù)就會產(chǎn)生如下的計算:(cube(2+0.001) - cube(2)/0.001關于lambda的一點好玩的地方函數(shù)式編程中“用函數(shù)來計算”的思想可以走向極端;我們甚至可以說萬事萬物(是的,我的意思是甚至是整數(shù),真值,假值這樣的東西,也就是字面上的萬事萬物)都可以表示成函數(shù)。一個十分聰明的家伙alonzo church指出如何做到這一點并產(chǎn)生一個了不起的成果,稱之為“l(fā)ambda演算”。我們并不會深入到church
15、的成果的細節(jié)中,但是會來簡單地看一些好玩的函數(shù)。讓我們看下我們對于“true”和“false”的定義:true = lambda x, y: xfalse = lambda x, y: yiff = lambda p, x, y: p(x, y)我們定義的true為一個函數(shù),它返回兩個參數(shù)中的前一個;而false則返回后一個參數(shù)。當我們看看我們怎么使用這樣的“true”和“false”的時候就會明白這種定義的邏輯了。調(diào)用iff(true, 2, 3)將返回2,而調(diào)用iff(false, 2, 3)則返回3。我們之前說的是所有可計算的建構都可以通過lambda定義出來。那么讓我們來試著建立一個基
16、本的數(shù)據(jù)結構,一個“pair”。pair = lambda x, y: lambda f: f(x, y)這種定義有點小技巧:“pair”是一個接受兩個參數(shù)的函數(shù),并返回另一個函數(shù);與此同時,這個返回的函數(shù)接受一個參數(shù),并將這個參數(shù)運用在x和y上。當我們定義另兩個函數(shù)的時候這種思想就變得很明了了。first = lambda p: p(true)second = lambda p: p(false)現(xiàn)在,讓我們變得哲學一點并問一個問題:“什么是pair?”答案是:“如果存在兩個函數(shù)first和second使得first(p)為x且second(p)為y,則我們說p是這兩個x和y的一個pair。”讓我們這
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年充電設施建設資金申請與智能充電解決方案研究報告
- 2025年沙盤模型制作項目申請報告
- 2025年醫(yī)藥企業(yè)研發(fā)外包(CRO)模式下的項目管理與團隊協(xié)作報告
- 2025-2030中國氯硝柳胺市場運行狀況及未來投資走勢預測報告
- 烏蘭察布職業(yè)學院《毽球運動》2023-2024學年第一學期期末試卷
- 洛陽職業(yè)技術學院《筆譯實訓2》2023-2024學年第一學期期末試卷
- 鞋類設計師(功能鞋方向)崗位面試問題及答案
- 2025屆廣東梅州第一中學高一下化學期末統(tǒng)考試題含解析
- 云南省文山馬關實驗高級中學2025屆高二化學第二學期期末質(zhì)量檢測試題含解析
- 甘肅省白銀市會寧縣2025屆高一化學第二學期期末達標檢測模擬試題含解析
- 2025年大學英語四級考試題及答案
- 隨州市城市規(guī)劃管理技術規(guī)定
- 綠色食品高粱生產(chǎn)技術操作規(guī)程
- 機械原理課程設計說明書精壓機
- 三年級除法豎式謎
- 口腔修復學-全口義齒修復課件
- 抖音快閃自我介紹(含背景音樂)
- 中國南方人才市場辦事指引
- 3、焊縫(焊道、焊口)寬度計算公式
- 天車工考試考試試題
- 抗體藥物中試項目可行性研究報告寫作范文
評論
0/150
提交評論