![系列4python之詳細初學者教程講義_第1頁](http://file4.renrendoc.com/view/875d5bc4e5889bfabe56a558b57f674c/875d5bc4e5889bfabe56a558b57f674c1.gif)
![系列4python之詳細初學者教程講義_第2頁](http://file4.renrendoc.com/view/875d5bc4e5889bfabe56a558b57f674c/875d5bc4e5889bfabe56a558b57f674c2.gif)
![系列4python之詳細初學者教程講義_第3頁](http://file4.renrendoc.com/view/875d5bc4e5889bfabe56a558b57f674c/875d5bc4e5889bfabe56a558b57f674c3.gif)
![系列4python之詳細初學者教程講義_第4頁](http://file4.renrendoc.com/view/875d5bc4e5889bfabe56a558b57f674c/875d5bc4e5889bfabe56a558b57f674c4.gif)
![系列4python之詳細初學者教程講義_第5頁](http://file4.renrendoc.com/view/875d5bc4e5889bfabe56a558b57f674c/875d5bc4e5889bfabe56a558b57f674c5.gif)
版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
有助于保持一致性,因為你只需改變單個的拷貝而無須去尋找再修改大量代碼的拷貝。后將著重介紹python函數的其他特性.declaration/definitiondeffoo():print'bar'functionobject/referencefoofunctioncall/invocationvs沒有返回值的函數。從后面內容你會看到,pythonNone11.1.2.返回值與函數類函數會向調用者返回一個值,而實際編大偏函數更接近過程,不顯示地返回任何東西。把c“void"python>>>def...printo>>>res=o>>>>>><typedefreturn -defreturn'abc',[42,'python'],讓人真的以為可以返回多個對象。如果我們要恰當地給這個元組加上括號,bar()的定義看起來會defreturn('abc',[4-2j,'python'],從返回值的角度來考慮,可以通過很多方式來元組。接下來的3種保存返回值的方式是等的>>>aTuple=>>>x,y,z=>>>(a,b,c)=>>>('abc',[(4-2j),'python'],>>>x,y,('abc',[(4-2j),'python'],>>>(a,b,('abc',[(4-2j),'python'],x,y,za,b,c用單一變量對其進行。(參見6.18.3)NonepythonNone.那么調用者們起來并以一個元組返回。是的,盡管我們聲稱python比諸如c那樣只允許一個返回值的語言靈活的多,但是老實說,python11.1pythonpython態(tài)地確定類型而且函數能返回不同類型的值,所以沒有進行直接的類型關聯(lián)。因為重載并不是語言特性,程序員需要使用type()這個內建函數作為,來處理有著不同參數類型的函數的多重以模擬類C語言的函數重載(以參數不同選擇函數的多個原型)。調用函函數操作同大多數語言相同,我們用一對圓括號調用函數。實際上,有些人認為(())是一個雙字符操作符。正如你可能的,任何輸入的參數都必須放置在括號中。作為函數的一部分,括號也關鍵字參舉個簡單的例子,比一個函數foo(),偽代碼如下deffoo_suite#presumablydoessomeprocessingwith標準調用foo():foo(42)foo('bar')defnet_conn(host,net_conn('kappa',host參數得到字符串'kappa',port參數得到整數8080.當然也可以不按照函數中的參數順序net_conn(port=8080,當參數允許"缺失“的時候,也可以使用關鍵字參數.這取決于函數的默認參數,在下一默認參默認參數就是了默認值的參數。因為給參數賦予了默認值,所以,在函數調用時,不向該參數傳入值也是允許的。在11.5.2章對默認參數進行更全面的介紹。參數參數)或字典(關鍵字參數)作為參數組傳遞給函數 在本章中討論這兩種形式?;鵩unc(*tuple_grp_nonkw_args,tuple_grp_nonkw_args是以元組形式體現的非關鍵字參數組,dict_grp_kw_args是裝有關鍵字參數的字典。正如我們已經提到的,在這章對這兩者進行全面介紹,現在你只需知道,存在這樣的特性允許你把變量放在元組和/或者字典里,并在沒有顯式地對參數進行逐個的情況下,func(positional_args,*tuple_grp_nonkw_args,apply()內建函數。(PriortoPython1.6,suchargument例表發(fā)送給合的適算術函數.(我們也會在原來版本中哪些地方會用到apply())參數,因為這些是二元運算符/運算。接著選擇任意的數字作為算子。因為我們沒打算在這個程序的基礎版本中支持負數,所以兩個數字的列表按從大到小的順序排序,然后用這個參數列表11.131#!/usr/bin/env23fromoperatorimportadd,6ops={'+':add,'-':7MAXTRIES=8defop=choice('+-nums=[randint(1,10)foriinans=pr='%d%s%d='%(nums[0],op,oops=whileifint(raw_input(pr))==printifoops==print'answer\n%s%d'%(pr,print'incorrect...tryoops+=except(KeyboardInterrupt,EOFError,print'invalidinput...tryagain'defwhileopt=raw_input('Again?ifoptandopt[0]==except(KeyboardInterrupt, =='mainLines1–Lines在這個應用程序中我們用的全局變量有:一個包含了運算符和與其相關聯(lián)的函數的集合(字典),一個決定在給出正解之前,用戶有多少次機會嘗試給出答案的整型變量。函數字典的鍵值是運算符的符號,程序通過查字典找到合適的算術函數。Linesdoprob()函數是應用程序的引擎。該函數隨機選擇一個操作并生成兩個操作數,同時為了第十行用了random.choice()函數。它用于獲取一個序 我們案例中運算符號的字符串-以僅僅用兩次randint()來獲得我們的操作數,比如,nums[randint(1,10),randint(1,10)是為了讓你能看看列表解析的又一個例子,我們沒有這樣做,而且使用列表解析更易于擴展和升級, 位。如果你使用的是更早一點的python版本,你要么:增加一個反序的比較函數來獲得倒轉的排序,如:lambdax,y:cmp(y,x),認為它是一個單行的函數。這樣寫apply(ops[op],nums),而不是ops[op](*nums)輸入或者允許嘗試的次數(3)被耗盡才終止運行。這允許程序接受不合法Lines程序的主是main(),如果直接運行,程序將自頂向下的運行。如果被作為模塊導入,導入者要么調用doprob()函數來開始執(zhí)行,要么調用main()來進入程序控制。main()簡單地調用doprob()使用戶與的主要功能進行交互,并負責提示用戶退出或者嘗試下一個問題。$7-2=5correctAgain?7*6=42correctAgain?7*3=incorrect...try7*3=incorrect...try7*3=sorry...theanswer7*3=7*3=21correctAgain?7-5=2correctAgain?[y]創(chuàng)建函11.3.1.defdef"functionation_string"標題行由def關鍵字,函數的名字,以及參數的集合(如果有的話)組成。def子句的剩余部分包def'returnsasalutorystringcustomizedwiththeinput'returno"+str(who)11.3.2.與定義比11.3.3前向def>>>inTraceback(innermostlast):File"<stdin>",line1,in?File"<stdin>",line3,infooNameError:defprint'indef>>>foo()infoo()indefdefprint'in>>>infoo()in11.3.4.函數屬pyhonfoobarx個模塊中使用了相同的變量名字,這也是安全的,因為句點屬性標識對于兩個模塊意味了不同名空間,比如說,在這段代碼中沒有名字:importfoo,bar在本章的稍后部分以及第12python的模塊中進行討論)def'foo()--properlycreateddocbar.doc='Oops,forgotthedocstrabove'bar.version=0.1上面的foo()中,我們以常規(guī)地方式創(chuàng)建了我們的文檔字串,比如,在函數后第一個沒有help()顯示會比用doc屬性更漂亮,但是你可以選擇你喜歡的方式)>>>Helponfunctionfooin mainfoo()--properlycreateddoc>>>print>>>printfoo.foo()--properlycreateddoc>>>printbar.Oops,forgotthedocstr注意我們是如何在函數外定義一個文檔字串。然而我們仍然可以就像平常一樣,在運行時刻它。然而你不能在函數的中屬性。換句話說,在函數中沒有'self‘這樣的東西dict['version']內部/內嵌函defdefprint'bar()print'foo()called'foo()calledbar()NameError:name'bar'isnot內部函數一個有趣的方面在于整個函數體都在外部函數的作用域(即是你可以一個對象的講述。如果內部函數的定義包含了在外部函數里定義的對象的(這個對象甚至可以是在外部函11.3.6*函數(與方法)裝僅是當一個函數或者方法的時候,才會應用的額外調用。def:類方法在2.2python中的時候,實現方法很笨拙:defstaticFoo()::staticFoo=:(要澄清的是對于那個版本,這不是最終的語法)在這個類的中,我們定義了叫staticFoo()的方法?,F在因為打算讓它成為靜態(tài)方法,我們省去它的self參數,而你會在12章中看到,self參數在標準的類方法中是必需的。接著用staticmethod()內建函數來將這個函數“轉化“為靜態(tài)方法,但是在defstaticFoo()staticFoostaticmethod(sta-ticFoo)顯得有classdefstaticFoo()::deffunc(arg1,arg2,...):deffunc(arg1,arg2,...):passfunc=deco2(deco1(func))(g·f)(x)g(f(x))pythondef: 有參數和無參數的裝deffoo(): foo= deffoo():pass.. 函數對象,而該函數對象正是以foo作為其參數的裝飾器。簡單的說來:foo deffunc():Thisisequivalentto:func=的,該中裝飾器不帶任何參數。例子11.8就是含有無參裝飾器的中間。那么什么是裝飾11.2修飾符舉例子通過顯示函數執(zhí)行的時間"裝飾"了一個(沒有用的)1611.21#!/usr/bin/env23fromtimeimportctime,4defdefprint'[%s]%s()called'%ctime(),returnreturndef19foriin2021[SunMar1922:50:282006]foo()[SunMar1922:50:332006]foo()[SunMar1922:50:342006]foo()5-10tsfunc()函數是一個顯示何時調用函數的時戳的裝飾器。它定義了一個內部的函數wrappedFunc(),該函數增加了時戳以及調用了目標函數。裝飾器的返回值是一個Lines我們用空函數體(什么都不做)來定義了foo()函數并用tsfunc()來裝飾。為證明我們的設想,立5(4+11pythonlangugaereference,python2.4What’sNewinPython2.4”的文檔PEP318中來閱讀關于裝飾器的內容。傳遞函當學門如C的語言時,函數指針的概念是一個高級話題,但是對于函數就像其他對象的python來說就不是那么回事了.函數是可以被的(或者以其他變量作為其別名,也作為參見14章)在以上的描述中,我們注意到可以用其他的變量來做作為函數的別名對象的賦值給這個變量。如果對象是函數的話,這個對象所有的別名都是可調用的。>>>def...print'in>>>bar=infoo()方式來調用bar()。確定你明白"foo"(函數對象的)和"foo()"(函數對象的調用)的區(qū)別。>>>o()foobar()中。bar(fooargfunc來作為其別名就如同面的例子中我們把foo賦給bar一樣?,F在我們來研究下一個更加實際的例子,numconv.py,代碼在例子11.3中給出一個將函數作為參數傳遞,并在函數體內調用這些函數,更加實際的例子。這個用傳入的轉換函數簡單將一個序列的數轉化為相同的類型。特別地,test()函數傳入一個內建函數int(),long(),或者float()來執(zhí)行轉換。1#!/usr/bin/envpython3defconvert(func,4'conv.sequenceofnumberstosame5return[func(eachNum)foreachNuminseq]7myseq=(123,45.67,- 8printconvert(int,9printconvert(long, printconvert(float,$[123,[123L,,][123.0,形式參位置參外,沒有任何默認參數(見下一個部分)的話,傳入函數(調用)的參數的精確的數目必須和>>>deffoo(who):#definedforonly1...printo',>>>foo()#0arguments...BADTraceback(innermostlast):File"<stdin>",line1,in?TypeError:notenougharguments;expected1,got>>>foo('World!')#1argument...WORKSo>>>foo('Mr.','World!')#2arguments...BADTraceback(innermostlast):File"<stdin>",line1,in?TypeError:toomanyarguments;expected1,gotTypeError??纯?,python無論何時調用函數,都必須提供函數的所有位置參數??梢圆话次粚㈥P鍵字參數傳入函數,給出關鍵字來匹配其在參數列表中的合適的位置是被準予的(可以回顧11.2.2)11.5.2.默認參數的標題行中給出。c++也支持默認參數,和python有同樣的語法:參數名等號默認值。這個deffunc(posargs,defarg1=dval1,"functionation_string"為什么用默認參APIapi>>>defreturn+(cost*>>>taxMe(100)>>>taxMe(100,在上面?zhèn)€例子中,)函數以一個項目的成本輸入參數,計算出附加了銷售稅的。成本是一個必需的參數,但稅率是一個默認參數(在我們的例子中為8.25%?;蛟S你是一個零售商,生意上的大部分客戶來自相同的州或者國家。不同地方稅率的顧客期望看見他們與當地銷售稅率相對應的價格總量。為了覆蓋默認的稅率,你所要做的就是提供一個參數值,比如在上面taxMe(100,0.05)5%稅率,你提供了一個參數作為稅率參數,所以覆蓋或者0.0825>>>deftaxMe2(rate=0.0825,...returncost*(1.0+SyntaxError:non-defaultargumentfollowsdefault讓我們再看下關鍵字參數,用我們的defnet_conn(host,net_conn('kappa',net_conn(port=8080,然而,如果默認參數引入這個等式,情況就會不同,雖然上面的調用仍然有效。讓我們修改下net_conn()的以使端口參數有默認值80,再增加另外的名為stype(服務器的類型)默認defnet_conn(host,port=80,net_conn('phaze',8000, #nodefargsnet_conn('kappa')#bothdefargsnet_conn('chino',stype='icmp')#useportdefnet_conn(stype='udp',host='solo')#useportdefnet_conn('deli',8080)#usestypedefnet_conn(port=81,host='chino')#usestypedefnet_conn()的調用中。關鍵字參數已經被證明能給不按順序的位置參數提供參數,結合默認參數,它們同樣也能被用于跳過缺失參數,上面例子就是極好的。默認函數對象參數我們現在將給出另外一個證明默認參數會讓人受益的例子。grabWeb.py,在例子11.4中給出,是一個主要目的是從互聯(lián)網上抓取一個Web頁面并暫時到一個本地文件中用于分析的簡單web(通過測量可性或者速度。process()例子抓取網頁這段了一個web頁面(默認為本地的www服務器)并顯示了html文件的第一個以及最后download()函數的雙默認參數允許用不同的urls或者指定不同的處理函數來進行1#!/usr/bin/env23fromurllibimporturlretrievedefforeachLineinifnotreturndeffirstLast(f=open(lines=printprintdefdownload(url=retval=exceptretval=ifretval:#dosome =='main$<!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML3.2可變長度的參在函數中不是顯式命名的,因為參數的數目在運行時之前是未知的(甚至在運行的期間,每次函數中命名的。由于函數調用提供了關鍵字以及非關鍵字兩種參數類型,python用兩種方法來11.2.4*和**符號來指定元組和字典的元素作為非關鍵字以及關鍵字參數的方法。在這個部分中,再次使用相同的符號,但是這次在函數的非關鍵字可變長參數(元組當函數被調用的時候,所有的形參(必須的和默認的)都將值賦給了在函數中相對應的局悉(va_list,va_arg,以及省略號[])。Pythondeffunction_name([formal_args,] deftupleVarArgs(arg1,arg2='defaultB','displayregularargsandnon-keywordvariableprint'formalarg1:',arg1print'formalarg2:',arg1foreachXtrArgintheRest:print'anotherarg:',eachXtrArg>>>tupleVarArgs('abc')formalarg1:abcformalarg2:defaultB>>>tupleVarArgs(23,formalarg1:formalarg2:>>>tupleVarArgs('abc',123,'xyz',456.789)formalarg1:abcformalarg2:123anotherarg:xyzanotherarg:456.789關鍵字變量參數deffunction_name([formal_args,][*vargst,] ation_string為了區(qū)分關鍵字參數和非關鍵字非正式參數,使用了雙星號(**。**是被重載了的以便不與冪運算發(fā)生。關鍵字變量參數應該為函數定義的最后一個參數,帶**。我們現在展示一個如何defdictVarArgs(arg1,arg2='defaultB','display2regularargsandkeywordvariableprint'formalarg1:',arg1print'formalarg2:',foreachXtrArginprint'Xtraarg%s:%s'%\(eachXtrArg,str(theRest[eachXtrArg]))>>>dictVarArgs(1220,740.0,c='grail')formalarg1:1220formalarg2:740.0Xtraargc:grail>>>dictVarArgs(arg2='tales',c=123,d='poe',arg1='mystery')formalarg1:mysteryformalarg2:talesXtraargc:123Xtraargd:poe>>>dictVarArgs('one',d=10,e='zoo',men=('freud','gaudi'))formalarg1:oneformalarg2:Xtraargmen:('freud','gaudi')Xtraargd:10Xtraarge:defnewfoo(arg1,arg2,*nkw,displayregularargsandallvariableprint'arg1is:',arg1print'arg2is:',arg2foreachNKWinnkw:print'additionalnon-keywordarg:',eachNKWforeachKWinprint"additionalkeywordarg'%s':%s"%\(eachKW,kw[eachKW])>>>newfoo('wolf',3,'projects',freud=90,arg1is:wolfarg2is:additionalnon-keywordarg:projectsadditionalkeywordarg'freud':90additionalkeywordarg'gamble':11.6.3調用帶有可變長參數對象11.2.4*和**來指定參數集合。接下來帶著對函數接受變長參數的些許偏見,我們會向你展示那種語法的例子,我們現在將用面部分定義的,我們的newfoo(),來測試新的調用語法。我們第一個newfoo()的調用將會使用舊風格的方式來分別列出所有的參數,甚至跟在所有形式參數之后的變>>>newfoo(10,20,30,40,foo=50,arg1is:arg2is:additionalnon-keywordarg:30additionalnon-keywordarg:40additionalkeywordarg'foo':50additionalkeywordarg'bar':>>>newfoo(2,4,*(6,8),**{'foo':10,'bar':arg1is:arg2is:additionalnon-keywordarg:6additionalnon-keywordarg:8additionalkeywordarg'foo':10additionalkeywordarg'bar':>>>aTuple=(6,7,>>>aDict={'z':argPAGEargPAGE2is:additionalnon-keywordarg:3additionalnon-keywordarg:6additionalnon-keywordarg:7additionalnon-keywordarg:8additionalkeywordarg'z':9additionalkeywordarg'x':4additionalkeywordarg'y':5函數式編全測試或通過,或需要給對潛在改善進行多次迭代計時的函數來工作。你所要做的就是創(chuàng)建一個設置測試環(huán)境的診斷函數,然后對有疑問的地方,調用函數。因為系統(tǒng)應該是靈活的,所以想testee,timeit()testit(),可能會對如今的軟件開發(fā)者我們現在將展示這樣的一個testit(函數的例子的源代(見例子11.5)留下該模塊給函數提供了一個執(zhí)試的環(huán)境。testit()函數使用了一個函數和一些參數,然后在異常處理的下,用給定的參數調用了那個函數。如果函數成功的完成,會返回True和函數的返回值給調用者。任何都會導致False和異常的原因一同被返回。(Exception是所有運行時刻異常的根類:復習第10章以獲得更詳細的資料Example11.5TestingFunctions1#!/usr/bin/envpython3deftestit(func,*nkwargs,**kwargs):56retval=func(*nkwargs,7result=(True,8exceptException,9result=(False, returndeffuncs=(int,long,vals=(1234,12.34,'1234',foreachFuncinprint'-'*foreachValinretval=ifprint'%s(%s)='%(eachF,`eachVal`),print'%s(%s)=FAILED:'%(eachF,`eachVal`),retval[1] =='main這樣的功能性,在測試中有兩個失敗的案例。這里是運行的輸出:$int(1234)=1234=12int('1234')=int('12.34')=FAILED:invalidliteralforint():long(1234)=1234Llong(12.34)=12Llong('1234')=1234Llong('12.34')=FAILED:invalidliteralforlong():float(1234)=float(12.34)=float('1234')=float('12.34')=函數式編的以4種內建函數和lambda表達式的形式出現11.7.1.函數與lambda“語句”代表了一個表達式,這個表達式的定義體必須和放在同一行。我們現在來演示下函數的語法:lambda[arg1[,arg2,...argN]]:筆記:lambda表達式返回可調用的函用合適的表達式調用一個lambda生成一個可以像其他函數一樣使用的函數對象。它們可被傳入給其他函數,用額外的別名化,作為容器對象以及作為可調用的對象被調用(如果需要的話,可以帶參數結果。它們和那些返回等價表達式計算值相同的函數是不能區(qū)分的。defreturn如果那樣的話,我們重寫下我們的true()函數以使其看其來像如下的東西:deftrue():returnlambda命名的true()函數的用法相當的明顯,但lambda就不是這樣。我們僅僅是這樣用,或者我們需要在某些地方用它進行賦值嗎?一個lambda函數自己就是無目地服務,正如在這里看到的:>>>lambda<function<lambda>atlambda(對象來,計數又回到零,然后被回收掉。為了保留住這個對象,它保存到一個變量中,以后>>>true=lambda>>>true()下個部分中,展示如何去使用帶函數式編程構建的lambda表達式。defadd(x,y):returnx+y?lambdax,y:x+defusuallyAdd2(x,y=2):returnx+y?lambdax,y=2:x+ydefshowAllAsTuple(*z):returnz?lambda*z:z>>>a=lambdax,y=2:x+>>>b=lambda*z:>>>b(23,(23,關于lambda最后補充一點:雖然看起來lambdda是一個函數的單行版本,但是它不等同于c++的內聯(lián)語句,這種語句的目的是由于性能的原因,在調用時繞過函數的棧分配。lambda內建函數apply()、filter()、map()、在這個部分中,看看apply(),filter(),map(),以及reduce()內建函數并給出一些如python象,lambda表達式提供了迅速創(chuàng)造這些函數的機制。11.2內建函 描apply(func[,nkw][,kw]) 用可選的參數來調用func,nkw為非關鍵字參數 filter(func,seq)b 使func返回值為ture的元素的序列。一個含有每個序列中元素集合的n個元組的列表。reduce(func,seq[,init])seq(果初始值init給定,第一個比較會是init和第一個序列元素而不正如前面提到的,函數調用的語法,現在允許變量參數的元組以及關鍵字可變參數的字典,在這里提及這個函數既是為了介紹下歷史,也是出于具有applay()函數的代碼的目的。filter()。想像下,去一個果園,走的時候帶著一包你filter()函數的主要前提。給定一個對象的序列和一個“過濾”函數,每個序列元素都filter(true)值元素添加到一個列表中。返回的對象是一個從原deffilter(bool_func,filtered_seq=[]ifreturnfiltered_seqFigure Howthefilter()built-infunction在圖11-1中,我們觀察到我們原始隊列在頂端,一個大小為n的隊列,元素從eq[0],你的函數確實返回一個真或假。如果bool_func()給每個序列的元返回一個真,那個元素將會入到返回的序列中。當迭代整個序列已經完成,filter()返回一個新創(chuàng)建的序列。我們下面展示在fromfromrandomimportdefreturnn%allNums=foreachNuminallNums.append(randint(1,99))printfilter(odd,allNums)代碼包括兩個函數:odd()(真)(假)Booleanmainmain()的目的是來產生10個在1到100filter()$pythonoddnogen.py[9,33,55,65]$pythonoddnogen.py[39,77,39,71,$pythonoddnogen.py[23,39,9,1,63,$pythonoddnogen.py[41,85,93,53,第一次重foreachNuminrange(9):allNums.append(randint(1,99))printfilter(lambdan:n%2,RefactoringPassallNums=foreachNuminallNums.append(randint(1,99))print[nforninallNumsifn%2]RefactoringPass(為了簡單,我們用一個較短的名字將randint()倒入到我們的代碼中)fromrandomimportrandintasprint[nfornin[ri(1,99)foriinrange(9)]if在最簡單的形式中,map()帶一個函數和隊列,將函數作用在序列的每個元素上,然后創(chuàng)建map(都加了2.pythonmap()如何運作的,11-2中闡釋的如defmap(func,seq):mapped_seq=[]foreachIteminseq:returnmapped_seqFigure Howthemap()built-infunction>>>map((lambdax:x+2),[0,1,2,3,4,[2,3,4,5,6,>>>map(lambdax:x**2,range(6))[0,1,4,9,16,25]>>>[x+2forxinrange(6)][2,3,4,5,6,7][0,1,4,9,16,25]map()map()map()會并行地迭代每個序列。在第一次調用時,map()會將每個序列的第一個元素到一個元組中,將func函數作用到map()map()mapped_seqmap(這里有些使用帶多個序列的map()的例子>>>map(lambdax,y:x+y,[1,3,5],[2,4,6])[3,7,11]>>>map(lambdax,y:(x+y,x-y),[1,3,5],[(3,-1),(7,-1),(11,->>>map(None,[1,3,5],[(1,2),(3,4),(5,想在一個新的內建函數,zip,被加進來之前的python2.0是很普遍的。而zip是這樣做的:>>>zip([1,3,5],[(1,2),(3,4),(5,reduce(,reducereduce(func,[1,2, =func(func(1,2),這就是可選初始化器出現的地方(initifinitisNone:#initializer?res=lseq.pop(0)#nores=init#foriteminlseq:#reducereturnres #returnresult4圖表(見圖11-4。reduce()的“oworld”是其一個簡單加法函數的應用或在這章前面看到的與之等價的lamdadefmySum(x,y):returnlambdax,y:>>>defmySum(x,y):return>>>allNums=range(5)#[0,1,2,3,>>>total=11-4reduce()>>>foreachNumin total=mySum(total,>>>print'thetotalis:',totalthetotalis:>>>print'thetotalis:',reduce((lambdax,y:x+y),range(5))thetotalis:10((((0+1)+2)+3)+4) 用list的頭兩個元素(0,1,調用mySum()來得到1,然后用現在的結果和下一個元素2來再次調用mySum(),再從這次調用中獲得結果,與下面的元素3配對然后調用mySum(),最終拿整個前4mySum()10,10即為最終的返回值。偏函數應currying的概念將函數式編程的概念和默認參數以及可變參數結合在一起。一個帶n個參數,curried的函數第一個參數為固定參數并返回另一個帶n-1個參數函數對象分別類似于LISP的(PFA,PFApython2.5functools模塊能很好的給用戶調用。簡add()mul(),operator模塊。這兩個函數僅僅是我們熟悉的+和*操作符的函數式接口,舉例來說,add(x,y)與x+y一樣。在我們的程序中,我們經常想要給和數字加一或者乘以100add(1,foo),add(1,bar),mul(100,foo),mul(100,bar)般的調用,擁有已存在的并使函數調用簡化的函數不是一件很美妙的事嗎?舉例來說,add1(foo),add1(bar),mul100,但是卻不用去實現函數add1()和mul100()?哦,現在用PFAs你就可以這樣做。你可以通過使用functional模塊中的partial()函數來創(chuàng)建PFA:>>>fromoperatorimportadd,>>>fromfunctoolsimport>>>add1=partial(add, #add1(x)==add(1,>>>mul100=partial(mul,100)#mul100(x)==mul(100,>>>mul100(10)>>>mul100(500)的參數,要么作為curried參數,要么作為那些 >>>baseTwo=partial(int,>>>baseTwo. ='Convertbase2stringtoan>>>baseTwo('10010')11.3.4部分base警basebaseTwoBADpartial(int,2),這可能會讓參數以錯誤的順序傳入int(),因為固定參數的總是放在運行時刻參數的左邊,比如baseTwoBAD(x)int(2,x)2,base'10010'>>>baseTwoBAD=partial(int,>>>Traceback(mostrecentcalllast):File"<stdin>",line1,inTypeError:anintegeris形參之后,所以baseTwo(x)==int(x,base=2).簡單GUI類的例子PFAsPFAs活動,等等。如果想要固定其中的一些參數,如讓所有的文本為藍底白字,你可以準確地以PFAs的方式,自定義為相似對象的偽模板。11.6GUI1#!/usr/bin/env23fromfunctoolsimport4import5root=MyButton=partial(Tkinter.Button,fg='white',b1=MyButton(text='Buttonb2=MyButton(text='Buttonqb=MyButton(text='QUIT',qb.pack(fill=Tkinter.X,b1=Tkinter.Button(root,fg='white',bg='blue',text='Button1')b2=Tkinter.Button(root,fg='white',bg='blue',text='Button2')qb=Tkinter.Button(root,fg='white',text='QUIT',bg='red',Reference“What’s變量作用標識符的作用域是定義為其在程序里的可應用范圍,或者即是我們所說的變量可見性。換句話說,就好像在問你自己,你可以在程序里的哪些部分去一個制定的標識符。變量可以是局全局變量與局部定義在函數內的變量有局部作用域,在一個模塊中別的變量有全局作用域。在編譯器理論里有名的“龍“書中,Aho,Sethi,ULLman以這種方法進行了總結。全局變量的一個特征是除非被刪除掉,否則它們的存活到運行結束,且對于所有的函數,他們的值都是可以被的,然而局部變量,就像它們存放的棧,暫時地存在,僅僅只依賴于定義它們的函數現階段是否處于活動。當一個函數調用出現時,其局部變量就進入它們的作用域。deffoo():local_str=returnglobal_str+筆記:搜索標識符(aka變量,名字,等等當搜索一個標識符的時候,python先從局部作用域開始搜索。如果在局部作用域內沒有找到那個名字,那么就一定會在全局域找到這個變量否則就會被拋出NameError在12正空現說子空間僅僅是將名字映射到對象名領域,現在使用的變量名字虛擬集合。作用域的概念和用于找到變量的名字空間搜索順序相關。當一個函數執(zhí)行的時候,所有在局部命名空間的名字都在局部作用域內。那就是當查找一個變量的時候,第一個被搜索的名字空間。如果沒有在那找到變量的話,那么就可能找到同名的全局變量。這些變量 (搜索)僅僅通過創(chuàng)建一個局部變量來“隱藏“或者覆蓋一個全局變量是有可能的?;叵胍幌?,局字空間是首先被搜索的,存在于其局部作用域。如果找到一個名字,搜索就不會繼續(xù)去尋找一個全局域的變量,所以在全局或者內建的名字空間內,可以覆蓋任何匹配的名字。同樣,當使用全局變量同名的局部變量的時候要。如果在賦予局部變量值之前,你在函數中(為了這個全局變量)使用了這樣的名字,你將會得到一個異常(NAMEERROR或者Unbound-LocalErrorpython版本。defprint"\ncallingfoo()..."bar=200print"infoo(),baris",barbar=100print"in main,baris",barfoo()print"\nin main,baris100callingfoo()...infoo(),baris main,baris(still)須使用global語句。global的語法如下:globalvar1[,var2[,...>>>is_this_global=>>>def...global...this_is_local=...is_this_global=...printthis_is_local+>>>printis_this_global11.8.3.作用域的數python從句法上支持多個函數嵌套級別,就如在python2.1中的,匹配靜態(tài)嵌套的作用域。然而,在2.1至前的版本中,最多為兩個作用域:一個函數的局部作用域和全局作用域。雖然存在多個函數的,但你不能超過兩個作用域。defm=defn=printm+n7>>>Traceback(innermostFile"<stdin>",line1,in?File"<stdin>",line7,infooFile"<stdin>",line5,inbarNameError:m在函數bar()內foo()的局部變量m是的因為m是為foo()的局部變量。從bar()的列表中。注意'printm'bar()的函數調用卻失敗了。幸運的是,由于python閉數也會到相同的問題。如果在一個內部函數里,對在外部作用域(但不是在全局作用域)的變量兩種。Closures從句法上看很簡單(和內部函數一樣簡單)但是仍然很有。為什么你會想要用closues?defcounter(start_at=0):count=[start_at]defcount[0]+=1returncount[0]returnincrcounter()做的唯一一件事就是接受一個初始化的的值來開始計數,并將該值賦給列表count唯一一個成員。然后定義一個incr()的內部函數。通過在變量count,我們創(chuàng)建了一個閉包因為它現在攜帶了整個counter()作用域。incr()增加了正在運行的count然后返回它。然后最后的魔法就是counter()返回一個incr,一個(可調用的)函數對象。如我們交互地運行這個函數,我 >>>count=>>>count2=掉這個類的call()特別方法來使他的實例可調用。這里我們能夠使用一對函數來做這事。追蹤閉包詞法的下面兩個部分包含了給高級讀者的材料……如果你愿意的話,你可以跳過去。討論如何func_closure','<cellat0x5ee30:intobjectat<int'w' <int'x'id=0x200377c<int'y' <int'z' 11.7#!/usr/bin/env2output='<int%rid=%#0xw=x=y=z=16def7x=y=z=29def10y=z=12def13z=14printoutput%('w',id(w),15printoutput%('x',id(x),16printoutput%('y',id(y),17printoutput%('z',id(z),z)19clo=20if21print"f3closurevars:",[str(c)forcin2223print"nof3closure2426clo=27if28print"f2closurevars:",[str(c)forcin2930print"nof2closure3133clo=34if35print"f1closurevars:",[str(c)forcin3637print"nof1closure38Lines這 Lines6–9,局部變量遮蔽或者隱藏了對他們同名的全局變量的。如果f2()使用了任何的定義在f1()作用Lines9–10,f1()f2()做相同的事,定義了局部變量yz,以及對一個內部如果對于f3()有任何的自由變量,他們會在這里顯示出來。,你會注意到對自由變量的是在單元對象里,或者簡單的說,單元。這些東西是什么呢?單元是在作用域結束后使自由變量的存活的一種基礎方法。Lines這個部分描繪了f3()的定義,創(chuàng)建一個局部的變量z。接著顯示w,x,y,z,這4個變量從最內f3f2(),或者f1(w的,所以,這是個全局f3(f2x,f1()的閉包變量。相似地,yf2()的閉包變量。最后,z是f3()的局部變量。Lines條件表達式不會求得True。這里的這段代碼僅僅是有修飾的目的。*高級閉包和裝飾器11.3.6deco.py。接下來就是稍微高級點的例子,來給你演示閉包的真正的。應用程序“l(fā)ogs"函數調用。用戶選擇是要在函數調1#!/usr/bin/env23fromtimeimporttimedefdeflog(f,*args,printfunction:args:defdefwrapper(*args,log(f,*args,returnf(*args,returndefdefwrapper(*args,now=returnf(*args,log(f,*args,print"timedelta:%s"%(time()-returnreturn{"pre":"post":exceptKeyError,raiseValueError(e),'mustbe"pre"or"post"'defprinto,",38$funcLog.pyo,World!function:<functionoat0x555f0>args:('World!',)kargs:timedelta:Lines5–10,描了logged()的的用戶請求。它應該在目標函數被調用前還是之后呢?logged()有3()以及post_logged()。lo示標準輸出函數的名字和參數。如果你愿意在“真實的世界中”使用該函數的話,你很有可能會把輸出寫到一個文件,數據庫,或者標準錯誤(sys.stderr)。logged()在28-32上是函數中非函數的最開始的代碼。用戶的選擇然后返回*()函數中的一個便能用目標函調用并包裹它。Lines數已經執(zhí)行之后,post_loggeed()會將函數調用寫入日志,而pre_logged()則是在執(zhí)行之前。logged(什么時候。然后返回的函數對象作為目標的函數的參數進行調用,比如,pre_logged(f)post_logged(f).兩個*logged()wrapper()的閉包。當合適將其寫入日志的時候,它便會Lines這段的主要部分簡單地裝飾了o()函數并將用修改過的函數對象一起執(zhí)行它。當你在38行調用o()的時候,它和你在35行創(chuàng)建的函數對象已經不是一回事了。34行的裝飾器用特殊的裝飾將原始函數對象進行了包裹并返回這個包裹后的o()版本。作用域和那些為函數局部變量的lambda表達式在這個函數體內是可以的;然而,在lambda語句中的表達式有和函數相同的作用域。你也可以認為函數和一個lambda表達式是同胞。x=defy=bar=lambda:x+yprintbar()然而,須在回顧下過去,去看下原來的python版本中讓代碼運行必需的,一種極其普遍的做法。在2.1之前會得到一個錯誤如同你在下面看到的一樣因為函數和lambda都>>>Traceback(innermostFile"<stdin>",line1,in?File"<stdin>",line4,inFile"<stdin>",line3,inNameError:在上面的例子中,雖然lambda表達式在foo()的局部作用域中創(chuàng)建,但他僅僅只能兩個作用域:它自己的局部作用域和全局的作用域(Section11.8.3).解決的方法是加入一個變量作為默認參數,這樣我們便能從外面的局部作用域傳遞一個變量到內部。在我們上面的例子中,我們將lambda的那一行修改成這樣:bar=lambday=y:yy(lambda的局部變量python變外部y值的可能性,比如:x=defy=bar=lambday=y:x+yprintbar()y=8printbar()ylambdalambda的定義沒有變。那時唯一替代的方案就是在lambda表達式中加入對函數局部變量y進行的局部變量z。x=defy=bar=lambdaz:x+zprintbar(y)y=printx=defy=bar=lambda:x+yprintbar(y)y=print變量作用域和名字空間少。我們要么在只能全局作用域的模塊的,要么在一個我們能函數局部作用域和全名字空間。從函數內部,局部作用域包圍了局部名字空間,第一個搜尋名字的地方。如果名字存在11.91#!/usr/bin/env2j,k=1,34def56j,k=3,7print"j==%dandk==%d"%(j,8k=9 defj=print==%dandk==%d"%(j,k=print==%dandk==%d"%(j,j=print==%dandk==%d"%(j,*N!?factorial(N)?1*2*3...*factorial(N)==N*(N-=N*(N-1)*(N-:=N*(N-1)*(N-2)...*3*2*factorial(NN*factorial(N-1).換句話說,為了獲得factorial(N)的值,需要計算factorial(N-1).而且,為了找到factorial(N-1),需要計算defifn==0orn==1:#0!=1!=returnreturn(n*factorial(n-11.10接口。這很容易明白因為他們僅僅只有一個方法,用于調用獲得下個元素的next()然而,除非你實現了一個迭代器的類,迭代器真正的并沒有那么“聰明“。難道調用函數還沒next()調用一樣簡單的東西?那就是的另外一個方面甚至更加強力用,可以暫?;蛘邟炱?,并從程序離開的地方繼續(xù)或者重新開始。在有調用者和(被調用的)協(xié)同足夠強大,但是在Python2.5的時候,得到了顯著的提高(見pep342)。這些提升讓更加接的時候,現在能返回控制。在調用的能掛起(返回一個結果)之前,調用生成器返回一個結果而不是阻塞等待那個結果返回。讓我們更進
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025合同模板學校食堂承包經營合同范本
- Unit2 He's cool(說課稿)2023-2024學年外研版(三起)四年級下冊
- 2025合同模板工程的變更范本
- 2025江蘇:安全責任寫進集體合同模板范本
- Unit1 School(說課稿)-2024-2025人教版(新起點)英語一年級上冊
- 2023七年級語文上冊 第四單元 綜合性學習 少年正是讀書時說課稿 新人教版
- Unit5 I'm cleaning my room(說課稿)-2023-2024學年人教精通版英語五年級下冊001
- 2024年九年級語文下冊 第二單元 第5課 孔乙己說課稿 新人教版
- 2024-2025學年高中化學下學期第20周 常見氣體的制備說課稿
- Unit 1 people of achievement Reading for writing 說課稿-2024-2025學年高中英語人教版(2019)選擇性必修第一冊
- 進模模具設計
- 完整,滬教版小學四年級英語上冊單詞表
- 2021年高考化學真題和模擬題分類匯編專題20工業(yè)流程題含解析
- 2023年北京市高考作文評分標準及優(yōu)秀、滿分作文
- 2023年大唐尿素投標文件
- 《鋼鐵是怎樣煉成的》名著閱讀(精講課件) 初中語文名著導讀
- 縮窄性心包炎課件
- 《工程電磁場》配套教學課件
- 職位管理手冊
- 東南大學 固體物理課件
- 行政人事助理崗位月度KPI績效考核表
評論
0/150
提交評論