第7章 函數(shù)定義與使用_第1頁(yè)
第7章 函數(shù)定義與使用_第2頁(yè)
第7章 函數(shù)定義與使用_第3頁(yè)
第7章 函數(shù)定義與使用_第4頁(yè)
第7章 函數(shù)定義與使用_第5頁(yè)
已閱讀5頁(yè),還剩44頁(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)介

第7章函數(shù)定義與使用董付國(guó)微信公眾號(hào):Python小屋本章學(xué)習(xí)目標(biāo)理解函數(shù)與代碼復(fù)用的關(guān)系熟練掌握函數(shù)定義與調(diào)用的語(yǔ)法理解遞歸函數(shù)的語(yǔ)法和執(zhí)行過(guò)程理解嵌套定義函數(shù)的語(yǔ)法和執(zhí)行過(guò)程理解位置參數(shù)、默認(rèn)值參數(shù)、關(guān)鍵參數(shù)和可變長(zhǎng)度參數(shù)的原理并能夠熟練使用理解實(shí)參序列解包的語(yǔ)法理解變量作用域的概念熟練掌握l(shuí)ambda表達(dá)式語(yǔ)法與應(yīng)用理解生成器函數(shù)的工作原理7.1函數(shù)定義與調(diào)用函數(shù)是代碼復(fù)用的重要實(shí)現(xiàn)方式之一。把用來(lái)解決某一類問(wèn)題的功能代碼封裝成函數(shù),可以重復(fù)利用這些功能,使得代碼更簡(jiǎn)潔,也更容易維護(hù)。除了內(nèi)置函數(shù)、標(biāo)準(zhǔn)庫(kù)函數(shù)和擴(kuò)展庫(kù)函數(shù),Python還允許用戶自定義函數(shù)。7.1.1基本語(yǔ)法在Python中,使用關(guān)鍵字def定義具名函數(shù),使用lambda表達(dá)式定義匿名函數(shù)。具名函數(shù)定義語(yǔ)法形式如下:def函數(shù)名([形參列表]):'''文檔字符串'''函數(shù)體7.1.1基本語(yǔ)法定義函數(shù)時(shí)需要注意的問(wèn)題主要有:1)函數(shù)名和形參名建議使用“見名知義”的英文單詞或單詞組合;2)不需要說(shuō)明形參類型,調(diào)用函數(shù)時(shí)Python解釋器會(huì)根據(jù)實(shí)參的值自動(dòng)推斷和確定形參類型;3)不需要指定函數(shù)返回值類型,這由函數(shù)中return語(yǔ)句返回的值來(lái)確定;4)上面的語(yǔ)法中方括號(hào)表示其中的參數(shù)列表可有可無(wú),即使該函數(shù)不需要接收任何參數(shù),也必須保留一對(duì)空的圓括號(hào),如果需要接收多個(gè)形式參數(shù)應(yīng)使用逗號(hào)分隔;5)函數(shù)頭部括號(hào)后面的冒號(hào)必不可少;6)函數(shù)體相對(duì)于def關(guān)鍵字必須保持一定的空格縮進(jìn),函數(shù)體內(nèi)部的代碼縮進(jìn)與前面章節(jié)學(xué)過(guò)的選擇結(jié)構(gòu)、循環(huán)結(jié)構(gòu)、異常處理結(jié)構(gòu)以及with語(yǔ)句具有相同的要求;7)函數(shù)體前面三引號(hào)和里面的文檔字符串可以不寫,但最好寫上,用簡(jiǎn)短語(yǔ)言描述函數(shù)功能、參數(shù)和返回值,使得接口更加友好;8)在函數(shù)體中使用return語(yǔ)句指定返回值,如果函數(shù)沒(méi)有return語(yǔ)句、有return語(yǔ)句但是沒(méi)有執(zhí)行到或者有return也執(zhí)行到了但是沒(méi)有返回任何值,Python都認(rèn)為返回的是空值None。7.1.1基本語(yǔ)法Python也允許自定義函數(shù)中說(shuō)明參數(shù)類型和返回值類型,但僅僅是說(shuō)明而已,并不真正起作用,不屬于強(qiáng)約束。例如,下面的代碼中雖然指定參數(shù)a和b以及函數(shù)返回值都為整數(shù),但實(shí)際上并不會(huì)有任何限制。deffunc(a:int,b:int)->int:returna+bprint(func(3,5))print(func(3.14,9.8))print(func('Python','小屋'))print(func([3],[4]))運(yùn)行結(jié)果為:812.940000000000001Python小屋[3,4]7.1.1基本語(yǔ)法例7-1編寫函數(shù),接收一個(gè)大于0的整數(shù)或?qū)崝?shù)r表示圓的半徑,返回一個(gè)包含圓的周長(zhǎng)與面積的元組,小數(shù)位數(shù)最多保留3位。然后編寫程序,調(diào)用剛剛定義的函數(shù)。frommathimportpidefget_area(r):'''接收?qǐng)A的半徑為參數(shù),返回包含周長(zhǎng)和面積的元組'''return(round(2*pi*r,3),round(pi*r*r,3))r=input('請(qǐng)輸入圓的半徑:')try:r=float(r)assertr>0except:print('必須輸入大于0的整數(shù)或?qū)崝?shù)')else:print(get_area(r))運(yùn)行結(jié)果為:請(qǐng)輸入圓的半徑:6(37.699,113.097)7.1.2遞歸函數(shù)定義與調(diào)用如果一個(gè)函數(shù)在執(zhí)行過(guò)程中特定條件下又調(diào)用了這個(gè)函數(shù)自己,叫作遞歸調(diào)用。遞歸函數(shù)用來(lái)把一個(gè)大型的復(fù)雜問(wèn)題層層轉(zhuǎn)化為一個(gè)與原來(lái)問(wèn)題本質(zhì)相同但規(guī)模更小、更容易解決或描述的問(wèn)題,只需要很少的代碼就可以描述解決問(wèn)題過(guò)程中需要的大量重復(fù)計(jì)算。在編寫遞歸函數(shù)時(shí),應(yīng)注意以下幾點(diǎn):1)每次遞歸應(yīng)保持問(wèn)題性質(zhì)不變;2)每次遞歸應(yīng)使得問(wèn)題規(guī)模變小或使用更簡(jiǎn)單的輸入;3)必須有一個(gè)能夠直接處理而不需要再次進(jìn)行遞歸的特殊情況來(lái)保證遞歸過(guò)程可以結(jié)束;4)函數(shù)遞歸深度不能太大,否則會(huì)引起內(nèi)存崩潰。7.1.2遞歸函數(shù)定義與調(diào)用例7-2已知正整數(shù)的階乘計(jì)算公式為n!=n×(n-1)×(n-2)×...×3×2×1,并且已知1的階乘為1,也就是1!=1。編寫遞歸函數(shù),接收一個(gè)正整數(shù)n,計(jì)算并返回n的階乘。deffac(n):#1的階乘為1,這是保證遞歸可以結(jié)束的條件ifn==1:#如果執(zhí)行到這個(gè)return語(yǔ)句,函數(shù)直接結(jié)束,不會(huì)再執(zhí)行后面的代碼return1#遞歸調(diào)用函數(shù)自己,使用越來(lái)越小的輸入,使得遞歸過(guò)程可以結(jié)束returnn*fac(n-1)#調(diào)用函數(shù),計(jì)算并輸出5的階乘print(fac(5))運(yùn)行結(jié)果為:1207.2函數(shù)參數(shù)函數(shù)定義時(shí)圓括號(hào)內(nèi)是使用逗號(hào)分隔開的形參列表,函數(shù)可以有多個(gè)參數(shù),也可以沒(méi)有參數(shù)。調(diào)用函數(shù)時(shí)將實(shí)參的引用傳遞給形參,在進(jìn)入被調(diào)函數(shù)內(nèi)部的瞬間,形參和實(shí)參引用的是同一個(gè)對(duì)象。在函數(shù)內(nèi)部,形參相當(dāng)于局部變量。由于Python中變量存儲(chǔ)的是值的引用,直接修改形參的值實(shí)際上是修改了形參變量的引用,不會(huì)影響實(shí)參。7.2函數(shù)參數(shù)defdemo(num):#剛剛進(jìn)入函數(shù)時(shí),形參與實(shí)參引用相同的對(duì)象result=num#內(nèi)置函數(shù)id()用來(lái)查看對(duì)象的內(nèi)存地址,不用過(guò)多關(guān)心#這里重點(diǎn)關(guān)心的是變量result、num的內(nèi)存地址與函數(shù)外的變量num相同print(id(num),id(result))whilenum>1:#每次執(zhí)行都會(huì)修改變量num和result的引用#此后num就和原來(lái)的實(shí)參再也沒(méi)有關(guān)系了num=num-1result=result*numreturnresultnum=5print(num,id(num))#調(diào)用函數(shù),傳遞實(shí)參print(demo(num))#原來(lái)的實(shí)參變量沒(méi)有受任何影響,內(nèi)存地址不變print(num,id(num))運(yùn)行結(jié)果為:514072660741916814072660741916814072660741916812051407266074191687.2函數(shù)參數(shù)如果調(diào)用函數(shù)時(shí)傳遞的實(shí)參是列表、字典、集合這樣的可變對(duì)象,函數(shù)內(nèi)部的代碼是否會(huì)影響實(shí)參的值要分兩種情況:1)如果在函數(shù)內(nèi)部像上面的代碼一樣直接修改形參的引用,不會(huì)影響實(shí)參;2)如果在函數(shù)內(nèi)部使用下標(biāo)的形式或者調(diào)用對(duì)象自身提供的原地操作方法,例如列表的append()、insert()、pop()等方法,或者集合的add()、discard()等方法,會(huì)影響實(shí)參。7.2函數(shù)參數(shù)defdemo(test_list,test_dict,test_set):#在列表尾部追加元素test_list.append(666)#在列表開始位置插入元素test_list.insert(0,666)#如果字典中有“鍵”為'name'的元素就修改對(duì)應(yīng)的“值”,否則插入新元素test_dict['name']='xiaoming'#如果集合中沒(méi)有元素666就放進(jìn)去,如果已經(jīng)存在就忽略test_set.add(666)data_list=[1,2,3]data_dict={'name':'xiaohong','age':23}data_set={1,2,3}demo(data_list,data_dict,data_set)print(data_list,data_dict,data_set,sep='\n')運(yùn)行結(jié)果為:[666,1,2,3,666]{'name':'xiaoming','age':23}{1,2,3,666}7.2.1位置參數(shù)位置參數(shù)是指調(diào)用函數(shù)時(shí)實(shí)參沒(méi)有任何說(shuō)明,直接放在括號(hào)內(nèi)調(diào)用函數(shù),按位置和順序傳遞實(shí)參,第一個(gè)實(shí)參傳遞給第一個(gè)形參,第二個(gè)實(shí)參傳遞給第二個(gè)形參,以此類推。實(shí)參和形參的順序必須嚴(yán)格一致,并且實(shí)參和形參的數(shù)量必須相同,否則會(huì)導(dǎo)致邏輯錯(cuò)誤得到不正確結(jié)果或者拋出TypeError異常并提示參數(shù)數(shù)量不對(duì)。deffunc(a,b,c):returnsum((a,b,c))print(func(1,2,3))print(func(4,5,6))運(yùn)行結(jié)果為:6157.2.1位置參數(shù)在Python3.8以及更新的版本中,允許在定義函數(shù)時(shí)設(shè)置一個(gè)斜線“/”作為參數(shù),斜線“/”本身并不是真正的參數(shù),僅用來(lái)說(shuō)明該位置之前的所有參數(shù)必須以位置參數(shù)的形式進(jìn)行傳遞。>>>deffunc(a,b,c,/):returnsum((a,b,c))>>>func(3,5,7)#所有參數(shù)都按位置傳遞15>>>func(3,5,c=7)#參數(shù)c沒(méi)有使用位置參數(shù)的形式,代碼出錯(cuò)TypeError:func()gotsomepositional-onlyargumentspassedaskeywordarguments:'c'7.2.2默認(rèn)值參數(shù)在定義函數(shù)時(shí)可以為形參設(shè)置默認(rèn)值,調(diào)用這樣的函數(shù)時(shí),可以不用為設(shè)置了默認(rèn)值的形參進(jìn)行傳遞實(shí)參,此時(shí)函數(shù)將會(huì)直接使用函數(shù)定義時(shí)設(shè)置的默認(rèn)值。也可以顯式為帶默認(rèn)值的形參傳遞實(shí)參,本次調(diào)用中不再使用形參的默認(rèn)值。在定義帶有默認(rèn)值參數(shù)的函數(shù)時(shí),任何一個(gè)默認(rèn)值參數(shù)右邊都不能再出現(xiàn)沒(méi)有默認(rèn)值的普通位置參數(shù),否則會(huì)拋出SyntaxError異常并提示“non-defaultargumentfollowsdefaultargument”。帶有默認(rèn)值參數(shù)的函數(shù)定義語(yǔ)法如下:def函數(shù)名(……,形參名=默認(rèn)值):函數(shù)體7.2.2默認(rèn)值參數(shù)deffunc(message,times=3):returnmessage*timesprint(func('重要的事情說(shuō)三遍!'))print(func('不重要的事情只說(shuō)一遍!',1))print(func('特別重要的事情說(shuō)五遍!',5))運(yùn)行結(jié)果為:重要的事情說(shuō)三遍!重要的事情說(shuō)三遍!重要的事情說(shuō)三遍!不重要的事情只說(shuō)一遍!特別重要的事情說(shuō)五遍!特別重要的事情說(shuō)五遍!特別重要的事情說(shuō)五遍!特別重要的事情說(shuō)五遍!特別重要的事情說(shuō)五遍!7.2.2默認(rèn)值參數(shù)如果定義函數(shù)時(shí)需要為部分變量設(shè)置默認(rèn)值,一定要注意盡量使用整數(shù)、實(shí)數(shù)、復(fù)數(shù)、元組、字符串、空值None或True/False這樣的不可變對(duì)象,要避免使用列表、字典、集合這樣的可變對(duì)象作為參數(shù)的默認(rèn)值,除非有特殊需要。函數(shù)參數(shù)默認(rèn)值是在定義函數(shù)時(shí)創(chuàng)建的對(duì)象,并且把默認(rèn)值的引用保存在函數(shù)的特殊成員“__defaults__”中,這是一個(gè)元組,里面保存了函數(shù)每個(gè)參數(shù)默認(rèn)值的引用,每次調(diào)用函數(shù)且不為帶默認(rèn)值的參數(shù)傳遞實(shí)參時(shí),都會(huì)使用特殊成員“__defaults__”里保存的引用。如果參數(shù)默認(rèn)值是可變對(duì)象并且在函數(shù)內(nèi)部有使用下標(biāo)或?qū)ο笞陨淼脑夭僮鞣椒▽?duì)參數(shù)進(jìn)行操作的語(yǔ)句,會(huì)影響后續(xù)調(diào)用。7.2.3關(guān)鍵參數(shù)關(guān)鍵參數(shù)是指調(diào)用函數(shù)時(shí)按參數(shù)名字進(jìn)行傳遞的形式,明確指定哪個(gè)實(shí)參傳遞給哪個(gè)形參。通過(guò)這樣的調(diào)用方式,實(shí)參順序可以和形參順序不一致,但不影響參數(shù)的傳遞結(jié)果,避免了用戶需要牢記參數(shù)位置和順序的麻煩,使得函數(shù)的調(diào)用和參數(shù)傳遞更加靈活方便。7.2.3關(guān)鍵參數(shù)deffunc(a,b,c):returnf'{a=},{b=},{c=}'print(func(a=3,c=5,b=8))print(func(c=5,a=3,b=8))運(yùn)行結(jié)果為:a=3,b=8,c=5a=3,b=8,c=57.2.3關(guān)鍵參數(shù)在Python3.8以及更新的版本中,允許在自定義函數(shù)中使用單個(gè)星號(hào)“*”作為參數(shù),但單個(gè)星號(hào)并不是真正的參數(shù),僅用來(lái)說(shuō)明該位置后面的所有參數(shù)必須以關(guān)鍵參數(shù)的形式進(jìn)行傳遞。>>>deffunc(a,*,b,c):returnf'{a=},{b=},{c=}'>>>print(func(3,5,8))#實(shí)參傳遞方式不對(duì),代碼出錯(cuò)TypeError:func()takes1positionalargumentbut3weregiven>>>print(func(3,b=5,c=8))a=3,b=5,c=8>>>print(func(3,c=5,b=8))a=3,b=8,c=5#關(guān)鍵參數(shù)的參數(shù)名必須是在函數(shù)定義中存在的或者可以接收的,否則出錯(cuò)>>>print(func(3,b=4,c=5,d=6))TypeError:func()gotanunexpectedkeywordargument'd'7.2.3關(guān)鍵參數(shù)在Python3.8以上的版本中,可以同時(shí)使用單個(gè)斜線和星號(hào)作參數(shù)來(lái)明確要求其他參數(shù)的傳遞形式。>>>deffunc(a,/,*,b,c):returnf'{a=},{b=},{c=}'>>>print(func(3,b=5,c=8))a=3,b=5,c=8>>>print(func(a=3,b=5,c=8))#參數(shù)a不能使用關(guān)鍵參數(shù)傳遞TypeError:func()gotsomepositional-onlyargumentspassedaskeywordarguments:'a'>>>print(func(3,5,8))#參數(shù)b和c不能使用位置參數(shù)傳遞TypeError:func()takes1positionalargumentbut3weregiven7.2.4可變長(zhǎng)度參數(shù)可變長(zhǎng)度參數(shù)是指形參對(duì)應(yīng)的實(shí)參數(shù)量不確定,一個(gè)形參可以接收多個(gè)實(shí)參。在定義函數(shù)時(shí)主要有兩種形式的可變長(zhǎng)度參數(shù):*parameter和**parameter,前者用來(lái)接收任意多個(gè)位置實(shí)參并將其放在一個(gè)元組中,后者接收任意多個(gè)關(guān)鍵參數(shù)并將其放入字典中。7.2.4可變長(zhǎng)度參數(shù)defdemo(a,b,c,*p):#參數(shù)p是個(gè)元組print(a,b,c)print(p)demo(1,2,3,4,5,6)print('='*10)demo(1,2,3,4,5,6,7,8)運(yùn)行結(jié)果為:123(4,5,6)==========123(4,5,6,7,8)7.2.4可變長(zhǎng)度參數(shù)defdemo(**p):#參數(shù)p是個(gè)字典foriteminp.items():print(item)demo(x=1,y=2,z=3)print('='*10)demo(a=4,b=5,c=6,d=7)運(yùn)行結(jié)果為:('x',1)('y',2)('z',3)==========('a',4)('b',5)('c',6)('d',7)7.2.5實(shí)參解包調(diào)用函數(shù)時(shí)可以對(duì)實(shí)參可迭代對(duì)象進(jìn)行解包,將其中的元素作為參數(shù)傳遞給形參。在調(diào)用函數(shù)并且使用可迭代對(duì)象作為實(shí)參時(shí),在實(shí)參可迭代對(duì)象前面加一個(gè)星號(hào)表示把其中的元素轉(zhuǎn)換為普通的位置參數(shù);在實(shí)參字典前面加一個(gè)星號(hào)表示把字典中的“鍵”轉(zhuǎn)換為普通的位置參數(shù);在字典前加兩個(gè)星號(hào)表示把其中的所有元素都轉(zhuǎn)換為關(guān)鍵參數(shù),元素的“鍵”作為實(shí)參的名字,元素的“值”作為實(shí)參的值。deffunc(a,b,c):print(f'{a=},{b=},{c=}')func(*[3,5,7])func(**{'a':97,'b':98,'c':99})運(yùn)行結(jié)果為:a=3,b=5,c=7a=97,b=98,c=997.3變量作用域變量起作用的代碼范圍稱為變量的作用域,不同作用域內(nèi)變量名字可以相同,互不影響。從搜索順序來(lái)看,由近及遠(yuǎn)有局部變量、nonlocal變量、全局變量和內(nèi)置對(duì)象。Python解釋器在訪問(wèn)變量時(shí),會(huì)按照這個(gè)順序進(jìn)行搜索并使用遇到的第一個(gè)同名變量,如果搜索過(guò)程結(jié)束仍沒(méi)有找到,引發(fā)異常并提示變量沒(méi)有定義。如果在函數(shù)內(nèi)只有引用某個(gè)變量值的操作而沒(méi)有為其賦值的操作,該變量默認(rèn)為全局變量、外層函數(shù)的變量或者內(nèi)置命名空間中的成員,如果都不是則會(huì)拋出異常并提示沒(méi)有定義。如果在函數(shù)內(nèi)有為變量賦值的操作,該變量就被認(rèn)為是局部變量,除非在函數(shù)內(nèi)賦值操作之前用關(guān)鍵字global或nonlocal進(jìn)行了聲明。7.3變量作用域在Python中有兩種創(chuàng)建全局變量的方式:1)在函數(shù)外部使用賦值語(yǔ)句創(chuàng)建的變量默認(rèn)為全局變量,其作用域?yàn)閺亩x的位置開始一直到文件結(jié)束;2)在函數(shù)內(nèi)部使用關(guān)鍵字global聲明變量為全局變量,其作用域從調(diào)用該函數(shù)的語(yǔ)句開始一直到文件結(jié)束。Python關(guān)鍵字global有兩個(gè)作用:1)對(duì)于在函數(shù)外創(chuàng)建的全局變量,如果需要在函數(shù)內(nèi)修改這個(gè)變量的值,并要將這個(gè)結(jié)果反映到函數(shù)外,可以在函數(shù)內(nèi)使用關(guān)鍵字global聲明要使用這個(gè)全局變量。2)如果一個(gè)變量在函數(shù)外沒(méi)有定義,在函數(shù)內(nèi)部也可以直接將一個(gè)變量聲明為全局變量,該函數(shù)執(zhí)行后,將增加一個(gè)新的全局變量。7.3變量作用域defdemo():globalx#聲明或創(chuàng)建全局變量,必須在使用變量x之前執(zhí)行該語(yǔ)句x=3#修改全局變量的值y=4#局部變量print(x,y)

#使用變量x和y的值x=5#在函數(shù)外部定義了全局變量xdemo()#本次調(diào)用修改了全局變量x的值print(x)try:print(y)except:print('不存在變量y')delx#刪除全局變量xtry:print(x)except:print('不存在變量x')demo()#本次調(diào)用創(chuàng)建了全局變量print(x)運(yùn)行結(jié)果為:343不存在變量y不存在變量x3437.3變量作用域除了局部變量和全局變量,Python還支持使用nonlocal關(guān)鍵字定義一種介于二者之間的變量。關(guān)鍵字nonlocal聲明的變量一般用于嵌套函數(shù)定義的場(chǎng)合(例如,在嵌套函數(shù)定義的場(chǎng)合中,內(nèi)層函數(shù)可以把外層函數(shù)中的變量聲明為nonlocal變量),要求聲明的變量已經(jīng)存在,關(guān)鍵字nonlocal不會(huì)創(chuàng)建新變量。7.3變量作用域defscope_test():defdo_local():spam="我是局部變量"defdo_nonlocal():nonlocalspam#要求spam必須是外層函數(shù)中定義的變量spam="我不是局部變量,也不是全局變量"defdo_global():globalspam#如果全局作用域內(nèi)沒(méi)有spam,自動(dòng)新建spam="我是全局變量"spam="原來(lái)的值"do_local()print("局部變量賦值后:",spam)do_nonlocal()print("nonlocal變量賦值后:",spam)do_global()print("全局變量賦值后:",spam)scope_test()print("全局變量:",spam)運(yùn)行結(jié)果為:局部變量賦值后:原來(lái)的值nonlocal變量賦值后:我不是局部變量,也不是全局變量全局變量賦值后:我不是局部變量,也不是全局變量全局變量:我是全局變量7.4lambda表達(dá)式語(yǔ)法與應(yīng)用lambda表達(dá)式常用來(lái)聲明匿名函數(shù),也就是沒(méi)有名字的、臨時(shí)使用的小函數(shù),雖然也可以使用lambda表達(dá)式定義具名函數(shù),但很少這樣使用。lambda表達(dá)式只能包含一個(gè)表達(dá)式,表達(dá)式的計(jì)算結(jié)果相當(dāng)于函數(shù)的返回值。lambda表達(dá)式的語(yǔ)法如下:lambda[形參列表]:表達(dá)式lambda表達(dá)式屬于Python可調(diào)用對(duì)象類型之一,下面代碼中的函數(shù)func和lambda表達(dá)式func在功能上是完全等價(jià)的。deffunc(a,b,c):returnsum((a,b,c))func=lambdaa,b,c:sum((a,b,c))7.4lambda表達(dá)式語(yǔ)法與應(yīng)用lambda表達(dá)式常用在臨時(shí)需要一個(gè)函數(shù)的功能但又不想定義函數(shù)的場(chǎng)合,例如內(nèi)置函數(shù)sorted(iterable,/,*,key=None,reverse=False)、max(iterable,*[,default=obj,key=func])、min(iterable,*[,default=obj,key=func])和列表方法sort(*,key=None,reverse=False)的key參數(shù),內(nèi)置函數(shù)map(func,*iterables)、filter(functionorNone,iterable)以及標(biāo)準(zhǔn)庫(kù)函數(shù)functools.reduce(function,sequence[,initial])的第一個(gè)參數(shù)。7.4lambda表達(dá)式語(yǔ)法與應(yīng)用fromfunctoolsimportreducefromrandomimportsample,seedseed(202208151630)#生成隨機(jī)數(shù)據(jù),包含5個(gè)子列表,每個(gè)子列表中包含10個(gè)整數(shù)#每個(gè)整數(shù)介于[0,20)區(qū)間,同一個(gè)子列表中的整數(shù)不重復(fù)data=[sample(range(20),10)foriinrange(5)]#按子列表的原始順序輸出,每個(gè)子列表占一行print(*data,sep='\n',end='\n===\n')#按子列表從小到大順序輸出,每個(gè)子列表占一行print(*sorted(data),sep='\n',end='\n===\n')#按每個(gè)子列表中第2個(gè)元素升序輸出print(*sorted(data,key=lambdarow:row[1]),sep='\n',end='\n===\n')#按每個(gè)子列表第2個(gè)元素升序輸出,如果第2個(gè)元素相等再按第4個(gè)升序輸出print(*sorted(data,key=lambdarow:(row[1],row[3])),sep='\n',end='\n===\n')7.4lambda表達(dá)式語(yǔ)法與應(yīng)用#第一個(gè)子列表中所有元素連乘的結(jié)果print(reduce(lambdax,y:x*y,data[0]),end='\n===\n')#第二個(gè)子列表中所有元素連乘的結(jié)果print(reduce(lambdax,y:x*y,data[1]),end='\n===\n')#每個(gè)子列表的第一個(gè)元素組成的新列表print(list(map(lambdarow:row[0],data)),end='\n===\n')#對(duì)角線元素組成的列表print(list(map(lambdarow:row[data.index(row)],data)),end='\n===\n')#最后一個(gè)元素最大的子列表print(max(data,key=lambdarow:row[-1]),end='\n===\n')#所有元素之和為偶數(shù)的子列表print(*filter(lambdarow:sum(row)%2==0,data),sep='\n',end='\n===\n')#所有元素之和小于等于80的子列表print(*filter(lambdarow:sum(row)<=80,data),sep='\n',end='\n===\n')#每列元素之和組成的新列表print(reduce(lambdax,y:list(map(lambdai,j:i+j,x,y)),data))7.5生成器函數(shù)定義與使用如果函數(shù)中包含yield語(yǔ)句,那么調(diào)用這個(gè)函數(shù)得到的返回值不是單個(gè)簡(jiǎn)單值,而是一個(gè)可以生成若干值的生成器對(duì)象,這樣的函數(shù)也稱生成器函數(shù)。生成器對(duì)象屬于迭代器對(duì)象之一,當(dāng)通過(guò)內(nèi)置函數(shù)next()、for循環(huán)遍歷生成器對(duì)象或其他方式(例如使用list()轉(zhuǎn)換成列表、使用tuple()轉(zhuǎn)換為元組)顯式“索要”數(shù)據(jù)時(shí),生成器函數(shù)中的代碼開始執(zhí)行,執(zhí)行到y(tǒng)ield語(yǔ)句時(shí),生成并提供一個(gè)值,然后暫停執(zhí)行,下次再“索要”數(shù)據(jù)時(shí)恢復(fù)執(zhí)行,不停地暫停與恢復(fù),直到用完所有數(shù)據(jù)為止。7.5生成器函數(shù)定義與使用deffib():a,b=1,1#序列解包,同時(shí)為多個(gè)對(duì)象賦值whileTrue:yielda#產(chǎn)生一個(gè)值,然后暫停執(zhí)行a,b=b,a+b#序列解包,修改對(duì)象的值gen=fib()#創(chuàng)建生成器對(duì)象foriinrange(10):

#斐波那契數(shù)列中前10個(gè)數(shù)字print(next(gen),end='')

#使用內(nèi)置函數(shù)next()獲取下一個(gè)值print()foriinfib():#創(chuàng)建生成器對(duì)象并使用for循環(huán)遍歷所有的數(shù)字ifi>100:#元素大于100時(shí)結(jié)束循環(huán)print(i,end='')breakprint()7.5生成器函數(shù)定義與使用deffunc():yieldfrom'abcdefg'#使用yieldfrom語(yǔ)句實(shí)現(xiàn)前面代碼中循環(huán)結(jié)構(gòu)的功能gen=func()print(next(gen))#使用內(nèi)置函數(shù)next()獲取下一個(gè)值print(next(gen))foritemingen:#遍歷剩余的所有的值print(item)defgen():yield1yield2yield3x,y,z=gen()#生成器對(duì)象支持序列解包print(x,y,z)print(*gen())#這也是序列解包的用法7.5生成器函數(shù)定義與使用例7-3編寫生成器函數(shù),模擬標(biāo)準(zhǔn)庫(kù)itertools中cycle()函數(shù)的工作原理。defmyCycle(iterable):iterable=tuple(iterable)whileTrue:foriteminiterable:yielditemc=myCycle(map(str,range(3)))foriinrange(20):print(next(c),end=',')print()c=myCycle(map(chr,range(65,69)))foriinrange(20):print(next(c),end=',')運(yùn)行結(jié)果為:0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,A,B,C,D,A,B,C,D,A,B,C,D,A,B,C,D,A,B,C,D,7.7綜合例題解析例7-4編寫遞歸函數(shù),判斷給定的字符串text是否為回文,也就是從前向后讀和從后向前讀都一樣的字符串。判斷回文有很多種方法,在Python中最簡(jiǎn)單的應(yīng)該是檢查表達(dá)式text==text[::-1]的值是否為True。如果使用遞歸的話思路是這樣的,先檢查字符串首尾字符是否一樣,如果不一樣就直接判斷不是回文;如果首尾字符一樣,那么原字符串是否為回文取決于去除首尾字符后得到的新字符串是否為回文。7.7綜合例題解析defcheck(text):#遞歸結(jié)束條件,長(zhǎng)度為0或1的字符串是回文iflen(text)in(0,1):returnTrue#遞歸結(jié)束條件,首尾字符不相等的字符串不是回文iftext[0]!=text[-1]:returnFalsereturncheck(text[1:-1])texts=('eye','rotator','madam','level','indeed',

'sky','python','畫中畫','天外天','拜拜','您吃了嗎','上海自來(lái)水來(lái)自海上','霧鎖山頭山鎖霧')fortextintexts:print(f'{text}:{check(text)}')運(yùn)行結(jié)果為:eye:Truerotator:Truemadam:Truelevel:Trueindeed:Falsesky:Falsepython:False畫中畫:True天外天:True拜拜:True您吃了嗎:False上海自來(lái)水來(lái)自海上:True霧鎖山頭山鎖霧:True7.7綜合例題解析例7-5編寫函數(shù),模擬猜數(shù)游戲。系統(tǒng)隨機(jī)在參數(shù)指定的范圍內(nèi)產(chǎn)生一個(gè)數(shù),玩家最大猜測(cè)次數(shù)也由參數(shù)指定,每次猜測(cè)之后系統(tǒng)會(huì)根據(jù)玩家的猜測(cè)進(jìn)行提示,玩家則可以根據(jù)系統(tǒng)的提示對(duì)下一次的猜測(cè)進(jìn)行適當(dāng)調(diào)整,直到猜對(duì)或者次數(shù)用完。7.7綜合例題解析fromrandomimportrandintdefguess(start,stop,maxTimes):#隨機(jī)生成一個(gè)整數(shù)value=randint(start,stop)foriinrange(maxTimes):prompt='開始猜吧:'ifi==0else'再猜一次:'try:#防止輸入不是整數(shù)的情況x=int(input(prompt))except:print('必須輸入整數(shù)')else:ifx==value:print('恭喜,猜對(duì)了!')breakelifx>value:print('太大了。')else:print('太小了。')else:print('次數(shù)用完了,游戲結(jié)束。')print('正確的數(shù)字是:',value)guess(100,110,3)7.7綜合例題解析例7-6編寫函數(shù),計(jì)算形式如a+aa+aaa+aaaa+...+aaa...aaa的表達(dá)式前n項(xiàng)的值,其中a為小于10的自然數(shù)。defdemo(a,n):asserttype(a)==intand0<a<10,'參數(shù)a必須介于[1,9]區(qū)間'assertisinstance(n,int)andn>0,'參數(shù)n必須為正整數(shù)'result,t=0,0foriinrange(n):t=t*10+aresult=result+treturnresultprint(demo(1,9))print(demo(6,8))運(yùn)行結(jié)果為:123456789740740687.7綜合例題解析例7-7假設(shè)一段樓梯共15個(gè)臺(tái)階,小明一步最多能上3個(gè)臺(tái)階,編寫程序計(jì)算小明上這段樓梯一共有多少種方法。defclimb_stairs(n):a,b,c=1,2,4foriinrange(n-3):c,b,a=a+b+c,c,breturncprint(climb_stairs(15))運(yùn)行結(jié)果為:57687.7綜合例題解析例7-8

溫馨提示

  • 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)論