Python良好編程習(xí)慣_第1頁(yè)
Python良好編程習(xí)慣_第2頁(yè)
Python良好編程習(xí)慣_第3頁(yè)
Python良好編程習(xí)慣_第4頁(yè)
Python良好編程習(xí)慣_第5頁(yè)
已閱讀5頁(yè),還剩5頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、python良好編程習(xí)慣如果進(jìn)行的是簡(jiǎn)單的處理,請(qǐng)使用字符串方法,這樣可避免復(fù)雜的正則表達(dá)式所帶來(lái)的錯(cuò)誤,并保證程序的可讀性。在原始字符串末尾使用反斜杠是語(yǔ)法錯(cuò)誤。正則表達(dá)式的模式字符串中常常包含反斜杠字符。使用原始字符串來(lái)創(chuàng)建模式,可以避免對(duì)其中每個(gè)反斜杠進(jìn)行轉(zhuǎn)義的必要,使模式字符串更容易理解。說(shuō)明:原始字符串(rawstring),也就是在字符串之前加上字符前綴r后創(chuàng)建的一個(gè)字符串。通常,如果在字符串中出現(xiàn),python會(huì)把它視為轉(zhuǎn)義字符,并試圖用正確的轉(zhuǎn)義序列替換元字符及其后續(xù)字符。但是,如果元字符出現(xiàn)在一個(gè)原始字符串中,python不會(huì)把它解釋成轉(zhuǎn)義字符,而是將其視為字面意義的反斜杠字

2、符。例如,python會(huì)將n解釋成換行符,但將rn解釋成兩個(gè)字符-一個(gè)反斜杠和一個(gè)n。用函數(shù)式編程語(yǔ)言(比如說(shuō)scheme)寫(xiě)的程序可以反映出數(shù)學(xué)表達(dá)式的結(jié)構(gòu);數(shù)學(xué)表達(dá)式是由若干函數(shù)字符串組成的,其中的每一個(gè)都能計(jì)算出一個(gè)結(jié)果并且不產(chǎn)生任何副作用。同樣的函數(shù)用同樣的參數(shù)去調(diào)用就會(huì)產(chǎn)生同樣的結(jié)果,這和調(diào)用時(shí)的上下文是無(wú)關(guān)的。用這樣的方法可以將我們的代碼優(yōu)雅地結(jié)構(gòu)化(并且一定程度上也起到了簡(jiǎn)化的效果)。python編程語(yǔ)言擁有所有讓它在函數(shù)式編程(fp)上有優(yōu)勢(shì)的特性。在這篇文章中,我們將從“pythonic”的角度來(lái)看一下fp中的一些有趣的思想如高階函數(shù)、閉包、lambda以及柯里化等等。什么是

3、函數(shù)式編程?作為程序的一部分,我們所寫(xiě)的函數(shù)只是在表面上和數(shù)學(xué)函數(shù)類似。比方說(shuō)我們寫(xiě)這么一個(gè)函數(shù):int current_balance = 100;int withdraw(int w)current_balance = current_balance - w;return current_balance;我們調(diào)用一次“withdraw(10)”之后90這個(gè)值將會(huì)被返回。再調(diào)用一次“withdraw(10)”則返回80。如果“withdraw”是一個(gè)“純”數(shù)學(xué)函數(shù)的話,那么兩次調(diào)用應(yīng)該返回同樣的值,因?yàn)槲覀儌鹘o它的參數(shù)值是一樣的。而我們的程序則“記住”了前次的調(diào)用(它有“狀態(tài)”)然后每次都返

4、回一個(gè)新的值 。一個(gè)如下的數(shù)學(xué)方程:y = f(a) + g(b) + f(a)有一個(gè)很好的屬性就是它可以被化簡(jiǎn)為:y = 2*f(a) + g(b)事實(shí)上如果有一個(gè)計(jì)算機(jī)程序是由一組會(huì)修改全面變量的函數(shù)構(gòu)成的話,我們是無(wú)法對(duì)它進(jìn)行這樣化簡(jiǎn)的。相比于生成一個(gè)數(shù)學(xué)證明,驗(yàn)證一個(gè)計(jì)算機(jī)程序的正確性更像是一個(gè)探索各種假設(shè)分析的情境的過(guò)程?!百x值”操作符也帶來(lái)了些問(wèn)題。讓我們簡(jiǎn)單地看一個(gè)計(jì)算階乘的循環(huán):# compute factorial of nint f = 1, n = 5;while (n 0) f = f * n;n = n - 1;return f;我們會(huì)犯的一個(gè)常見(jiàn)的錯(cuò)誤就是在循環(huán)體內(nèi)

5、交換兩個(gè)語(yǔ)句的順序。因?yàn)橘x值操作符改變了它左邊的符號(hào)的值,所以這讓我們?cè)诳紤]在我們的程序中每一個(gè)動(dòng)作的順序時(shí)需要格外的小心。函數(shù)式編程的范式鼓勵(lì)我們把程序結(jié)構(gòu)化成一系列“純”的函數(shù),這些函數(shù)沒(méi)有全局的狀態(tài)也不使用賦值操作符(注意這并不是所有情況下都可行的,很顯然一個(gè)銀行的系統(tǒng)就需要“記住”很多東西)。函數(shù)式編程人員使用遞歸的函數(shù)調(diào)用(循環(huán)可以當(dāng)成一種特殊的遞歸,于是特定的循環(huán)結(jié)構(gòu)“while”和“for”也就不需要了)來(lái)產(chǎn)生重復(fù)性的行為。函數(shù)則成為了我們的“一等公民”,比方說(shuō),它們可以被當(dāng)成參數(shù)傳給另一個(gè)函數(shù),也可以被別的函數(shù)返回,這就促成了我們稱之為“高階函數(shù)”的產(chǎn)生。當(dāng)和“閉包”這個(gè)思想結(jié)

6、合在一起的時(shí)候,這就成為了一個(gè)很強(qiáng)大的思想,它可以很簡(jiǎn)單地捕獲很多復(fù)雜的可計(jì)算模式。遞歸表示python中定義一個(gè)遞歸函數(shù)沒(méi)什么了不起的。這里是一個(gè)用python寫(xiě)的經(jīng)典階乘函數(shù):def fact(n):if (n = 0): return 1return n * fact(n - 1)作為一等公民對(duì)象的函數(shù)讓我們?cè)趐ython的命令行中定義兩個(gè)函數(shù),然后來(lái)做些實(shí)驗(yàn):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我們先將兩個(gè)函數(shù)存到數(shù)組中,然后用“a02”的方式來(lái)調(diào)用“sqr”。接著我們又定義一個(gè)叫“compose”的函數(shù),然后將“sqr”和“cube”這兩個(gè)函數(shù)作為參數(shù)傳給它們并進(jìn)行調(diào)用。注意這邊并沒(méi)有任何特殊的記號(hào),我們操作函數(shù)時(shí)就好像它們是像數(shù)組和數(shù)字之類的對(duì)象一樣。高階函數(shù)的威力structure and interpretation of computer programs,這本由abelson和sussman寫(xiě)的傳奇般的“指南書(shū)”中詳細(xì)地描述了高階函數(shù)的作用。一個(gè)“函數(shù)”(或子程序、輔程序、過(guò)程)被認(rèn)為是一種捕獲模式的機(jī)制。如果我們有如下形式的語(yǔ)句a*a*ab*b*b

8、c*c*c.我們可以想到要定義一個(gè)叫“cube”(立方)的函數(shù)來(lái)捕獲這種模式的本質(zhì)并給它一個(gè)名字。將函數(shù)當(dāng)成參數(shù)傳給別的函數(shù)的這種能力拓寬了這種“模式捕獲”機(jī)制的領(lǐng)域。讓我們來(lái)看一個(gè)簡(jiǎn)單的函數(shù),叫“sum”:def sum(a, b):if (a b): return 0else: return a + sum(a+1, b)這個(gè)函數(shù)將從“a”到“b”的所有數(shù)字進(jìn)行累加。我們嘗試著拓寬這個(gè)函數(shù)的領(lǐng)域,讓它具有操作任意序列的能力,比如說(shuō):1/(1*3) + 1/(5*7) + 1/(9*11) + .我們發(fā)現(xiàn)到上面的序列和下面這個(gè):1 + 2 + 3 + 4 + .有著相似之處,即它們都是“求和

9、”。我們想象一個(gè)變量“a”從1變到2,2變到3,然后一直這么做下去。這種從1到2的變化可以用一個(gè)函數(shù)來(lái)捕獲(就是一個(gè)簡(jiǎn)單的“加1”函數(shù))。在第一個(gè)序列中,這個(gè)變量是從1到5,5到9,9到11這么變化的。所以在這里的這種變化我們可以用一個(gè)“加4”的函數(shù)來(lái)捕獲。另一個(gè)小問(wèn)題是,這個(gè)數(shù)列中的通項(xiàng)并不是數(shù)字1、5、9、11等等而是1/(1*3)、1/(5*7)但是接著這種轉(zhuǎn)換也可以通過(guò)一個(gè)函數(shù)表示!我們觀察的結(jié)果可以用一個(gè)函數(shù)“sigma”表示出來(lái):def sigma(term, a, next, b):if(a b): return 0return term(a) + sigma(term, nex

10、t(a), next, b)然后看看我們?cè)趺赐ㄟ^(guò)“sigma”來(lái)計(jì)算這個(gè)序列的和:1/(1*3) + 1/(5*7) + 1/(9*11) + .我們來(lái)定義兩個(gè)函數(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)在我們就能只要定義兩個(gè)輔助函數(shù)就可以累積任意數(shù)列的和了。故事還沒(méi)有結(jié)束。我們可以想想怎么將“sigma”進(jìn)行泛化。我們注意到“sigma”只是使用了一個(gè)組合函數(shù)“add”來(lái)將一個(gè)序列中的各項(xiàng)“組合”起來(lái)。為什么不用一個(gè)泛化的過(guò)程來(lái)根據(jù)一個(gè)

11、用戶定義好并作為參數(shù)傳過(guò)來(lái)的函數(shù)來(lái)組合函數(shù)中的各項(xiàng)呢?讀者可以把這個(gè)當(dāng)成一個(gè)練習(xí)來(lái)試試!使用“l(fā)ambda”我們?cè)賮?lái)試試下面些命令:lambda x: x+4function at 0x402ba25cf = lambda x: x+4f(3)7lambda關(guān)鍵字創(chuàng)建了一個(gè)匿名函數(shù)。lambda的主體只能由一些簡(jiǎn)單的表達(dá)式組成。在上一個(gè)例子中,我們用lambda來(lái)創(chuàng)建一個(gè)函數(shù),這個(gè)函數(shù)接受一個(gè)參數(shù),并將它加4后返回。當(dāng)我們需要定義一個(gè)函數(shù)而只將這個(gè)函數(shù)用于傳遞給另一個(gè)函數(shù)的時(shí)候,我們應(yīng)當(dāng)想到使用“l(fā)ambda”。比如說(shuō):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ù)接受一個(gè)函數(shù)和一個(gè)列表作為參數(shù),然后將函數(shù)運(yùn)用在原列表的每一個(gè)元素上,并將得到的新列表返回。filter也是類似的,它返回的列表只由原列表中那些能使函數(shù)返回true的元素組成。閉包python允許嵌套的函數(shù)定義。def add(x):return lambda(y): x+y調(diào)用add(3)將返回一個(gè)帶單參數(shù)的函數(shù)?,F(xiàn)在這個(gè)返回的函數(shù)有一個(gè)特性它能記住它被創(chuàng)建時(shí)的環(huán)境。函數(shù)體中的“x”是我們?cè)谡{(diào)用“add”時(shí)提供給它的。我們把這樣的函數(shù)叫作“閉包”。調(diào)用add(3)(4)將使這個(gè)函數(shù)以x

13、 = 3和y = 4的值執(zhí)行。也許你已經(jīng)注意到了一些有趣的地方。我們并沒(méi)有定義一個(gè)接受兩個(gè)參數(shù)的“add”函數(shù),而是可以將一個(gè)單參數(shù)的函數(shù)嵌在另一個(gè)單參數(shù)的函數(shù)中,并產(chǎn)生相同的效果。我們也可以將這升到任意層次:def add3(x):return lambda y: lambda z: x+y+z現(xiàn)在我們就可以調(diào)用“add3(1)(2)(3)”了!這個(gè)思想在fp社區(qū)中被稱為“柯里化”。讓我們?cè)囍鴮?xiě)一個(gè)做“數(shù)值”微分的函數(shù)。def differentiate(f):return lambda x: (f(x+0.001) - f(x)/0.001這個(gè)函數(shù)可以這么試出來(lái):p = different

14、iate(cube)p(2)12用“cube”作為參數(shù)來(lái)調(diào)用differentiate會(huì)返回一個(gè)單參數(shù)函數(shù),這個(gè)函數(shù)會(huì)記得“f”的值等于“cube”?,F(xiàn)在,用2作為參數(shù)來(lái)調(diào)用這個(gè)函數(shù)就會(huì)產(chǎn)生如下的計(jì)算:(cube(2+0.001) - cube(2)/0.001關(guān)于lambda的一點(diǎn)好玩的地方函數(shù)式編程中“用函數(shù)來(lái)計(jì)算”的思想可以走向極端;我們甚至可以說(shuō)萬(wàn)事萬(wàn)物(是的,我的意思是甚至是整數(shù),真值,假值這樣的東西,也就是字面上的萬(wàn)事萬(wàn)物)都可以表示成函數(shù)。一個(gè)十分聰明的家伙alonzo church指出如何做到這一點(diǎn)并產(chǎn)生一個(gè)了不起的成果,稱之為“l(fā)ambda演算”。我們并不會(huì)深入到church

15、的成果的細(xì)節(jié)中,但是會(huì)來(lái)簡(jiǎn)單地看一些好玩的函數(shù)。讓我們看下我們對(duì)于“true”和“false”的定義:true = lambda x, y: xfalse = lambda x, y: yiff = lambda p, x, y: p(x, y)我們定義的true為一個(gè)函數(shù),它返回兩個(gè)參數(shù)中的前一個(gè);而false則返回后一個(gè)參數(shù)。當(dāng)我們看看我們?cè)趺词褂眠@樣的“true”和“false”的時(shí)候就會(huì)明白這種定義的邏輯了。調(diào)用iff(true, 2, 3)將返回2,而調(diào)用iff(false, 2, 3)則返回3。我們之前說(shuō)的是所有可計(jì)算的建構(gòu)都可以通過(guò)lambda定義出來(lái)。那么讓我們來(lái)試著建立一個(gè)基

16、本的數(shù)據(jù)結(jié)構(gòu),一個(gè)“pair”。pair = lambda x, y: lambda f: f(x, y)這種定義有點(diǎn)小技巧:“pair”是一個(gè)接受兩個(gè)參數(shù)的函數(shù),并返回另一個(gè)函數(shù);與此同時(shí),這個(gè)返回的函數(shù)接受一個(gè)參數(shù),并將這個(gè)參數(shù)運(yùn)用在x和y上。當(dāng)我們定義另兩個(gè)函數(shù)的時(shí)候這種思想就變得很明了了。first = lambda p: p(true)second = lambda p: p(false)現(xiàn)在,讓我們變得哲學(xué)一點(diǎn)并問(wèn)一個(gè)問(wèn)題:“什么是pair?”答案是:“如果存在兩個(gè)函數(shù)first和second使得first(p)為x且second(p)為y,則我們說(shuō)p是這兩個(gè)x和y的一個(gè)pair?!弊屛覀冞@

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論