官术网_书友最值得收藏!

1.4 函數(shù)

函數(shù)是指用于實(shí)現(xiàn)一個(gè)特定功能并能重復(fù)使用的代碼段。前面學(xué)到的input和print這些函數(shù)是Python語(yǔ)言的內(nèi)建函數(shù),可以直接使用。也可以自己定義函數(shù)來(lái)實(shí)現(xiàn)我們想要的功能,這樣的函數(shù)叫作用戶自定義函數(shù)。本節(jié)就來(lái)了解用戶自定義函數(shù)。

1.4.1 定義子函數(shù)

要想使用函數(shù),必須先定義它。

定義函數(shù)的格式為:

def函數(shù)名(變量名):

其中,變量名指?jìng)鬟M(jìn)子函數(shù)的數(shù)據(jù)在子函數(shù)內(nèi)部對(duì)應(yīng)的變量名,可以沒(méi)有,也可以有一個(gè)或者多個(gè)。函數(shù)名是在調(diào)用函數(shù)時(shí)要使用的名字,兩個(gè)函數(shù)不能有相同的變量名。也就是說(shuō),在Python中已經(jīng)存在print函數(shù),所以在創(chuàng)建自定義函數(shù)時(shí)不能以print作為變量名,但是可以使用Print作為變量名(一個(gè)字符大寫(xiě)了)。

最后,如果這是一個(gè)有返回值的函數(shù),要在函數(shù)的最后寫(xiě)上“return返回值”。

長(zhǎng)篇大論不如一個(gè)例子,這就來(lái)創(chuàng)建一個(gè)函數(shù)看看。

01  def Plus(a,b):

02    print(a+b)

03

04  def Hello():

05    num1=int(input("Hello! Please enter the first number:"))

06    num2=int(input("Please enter the second number:"))

07    return num1,num2

08

09  n1,n2=Hello()

10  Plus(n1,n2)

這是一個(gè)用于計(jì)算兩個(gè)數(shù)的和的程序。第一個(gè)函數(shù)Plus用于計(jì)算兩個(gè)數(shù)的和,第二個(gè)函數(shù)Hello用于向用戶問(wèn)好并輸入兩個(gè)數(shù)字。

Plus函數(shù)被調(diào)用時(shí)(第10行),需要提供兩個(gè)值。a對(duì)應(yīng)n1的值,b對(duì)應(yīng)n2的值,在函數(shù)內(nèi)部使用這兩個(gè)值時(shí)只能調(diào)用a和b,不能調(diào)用n1和n2。如果調(diào)用語(yǔ)句是Plus(3,5),那么a==3、b==5,a和b繼承它們對(duì)應(yīng)位置上的值。這個(gè)函數(shù)沒(méi)有返回值,只需要print,所以在函數(shù)結(jié)尾不需要寫(xiě)return。

從 Hello 函數(shù)的定義語(yǔ)句中可以看到,括號(hào)內(nèi)并沒(méi)有變量名,這代表調(diào)用函數(shù)時(shí)不需要提供任何值。在函數(shù)內(nèi),num1和num2存儲(chǔ)了兩個(gè)輸入的值,用return返回。Python和其他語(yǔ)言不同,可以同時(shí)返回多個(gè)值,而且可以是不同類型的值。返回多個(gè)值時(shí),在等號(hào)的左邊用多個(gè)變量接住,變量之間用逗號(hào)隔開(kāi);同樣,變量繼承它們對(duì)應(yīng)位置上的值。在程序中,n1繼承了num1的值,n2繼承了num2的值。

注意:由于程序是從上到下運(yùn)行(行數(shù)編號(hào)從小到大)的,所以函數(shù)必須在調(diào)用語(yǔ)句的上面定義。也就是說(shuō),程序第9行的代碼如果被換到第3行,程序就會(huì)報(bào)錯(cuò),因?yàn)檫@時(shí)Hello函數(shù)還沒(méi)有被定義。另外,和if、while和for語(yǔ)句相似,函數(shù)的定義語(yǔ)句下的代碼段也要有縮進(jìn)。

在這段程序中,做加法的簡(jiǎn)單任務(wù)不創(chuàng)建函數(shù)其實(shí)更簡(jiǎn)單。在復(fù)雜的程序中,使用自定義函數(shù)可以使解決問(wèn)題的過(guò)程簡(jiǎn)便直觀得多。

主函數(shù)的定義是程序的入口函數(shù)。其他的函數(shù)(不是主函數(shù)的函數(shù)叫作子函數(shù))和方法都在主函數(shù)中調(diào)用。

1.4.2 主函數(shù)

在C語(yǔ)言中,主函數(shù)和子函數(shù)之外的語(yǔ)句只能是定義語(yǔ)句。而在Python中,函數(shù)之外也可以有定義語(yǔ)句之外的語(yǔ)句,比如輸出等。Python程序運(yùn)行時(shí)只會(huì)運(yùn)行不在函數(shù)內(nèi)的代碼和主函數(shù)內(nèi)的代碼段,不會(huì)運(yùn)行子函數(shù)內(nèi)的代碼段。子函數(shù)內(nèi)的代碼段只有在被調(diào)用時(shí)才會(huì)運(yùn)行。

因?yàn)橛羞@個(gè)特性,如果程序的調(diào)用和被調(diào)用范圍僅限于本文件內(nèi),可以不編寫(xiě)主函數(shù),直接在所有子函數(shù)下面編寫(xiě)代碼就可以。但是,為了養(yǎng)成好的習(xí)慣和直觀性,建議在編寫(xiě)程序時(shí)加上主函數(shù)。本書(shū)為了簡(jiǎn)單易懂,有些代碼段不使用主函數(shù)。

下面我們來(lái)了解一下在Python中如何定義主函數(shù)。

01  if __name__=='__main__':

02    print("Inside")

運(yùn)行程序,輸出結(jié)果為:

Inside

if__name__=='__main__'是定義主函數(shù)的語(yǔ)句。定義函數(shù)的時(shí)候要注意代碼塊前面的縮進(jìn)(本質(zhì)上是if語(yǔ)句的格式)。

再來(lái)看一個(gè)例子:

01  def sq(num):

02    print(num*num)

03  print("Outside")

04  if __name__=='__main__':

05    print("Inside")

運(yùn)行程序,輸出結(jié)果為:

Outside

Inside

在函數(shù)外和主函數(shù)內(nèi)的輸出語(yǔ)句都被執(zhí)行了,而子函數(shù)sq因?yàn)闆](méi)有被調(diào)用,其中的輸出語(yǔ)句并沒(méi)有被執(zhí)行。

1.4.3 調(diào)用函數(shù)

在1.4.1節(jié)介紹子函數(shù)時(shí),就在程序中調(diào)用了我們定義的子函數(shù)。但是,不同的子函數(shù)有不同的調(diào)用方法。本節(jié)就來(lái)講解調(diào)用各種函數(shù)的規(guī)律。

在定義子函數(shù)時(shí),還要在函數(shù)的括號(hào)中定義好需要傳進(jìn)子函數(shù)的變量。調(diào)用函數(shù)的格式和為函數(shù)定義的需要傳進(jìn)函數(shù)的變量有關(guān)。調(diào)用函數(shù)時(shí)傳進(jìn)的數(shù)據(jù)是什么類型的變量,函數(shù)內(nèi)部對(duì)應(yīng)位置上的變量就會(huì)是同樣類型的。

比如,我們定義了一個(gè)函數(shù) calc,需要三個(gè)變量,最后返回的值是第一個(gè)變量和第二個(gè)變量的乘積減去第三個(gè)數(shù)的值,如圖1.29所示。

圖1.29 函數(shù)calc

函數(shù)定義和調(diào)用時(shí)的格式是這樣的:

01  def calc(a,b,c):

02    ans=a*b-c

03    return ans

04  ans=calc(2,3,4)

05  print(ans)

運(yùn)行程序,輸出結(jié)果:

2

如果在調(diào)用函數(shù)時(shí)寫(xiě)的是calc('2',3,4),那么函數(shù)就會(huì)在執(zhí)行的時(shí)候出錯(cuò),因?yàn)椋?'對(duì)應(yīng)的是a,3對(duì)應(yīng)的是b,4對(duì)應(yīng)的是c,string類型的變量無(wú)法和int類型的變量進(jìn)行計(jì)算。

值得注意的是,在調(diào)用函數(shù)時(shí),我們還使用了一個(gè)變量來(lái)存儲(chǔ)函數(shù)的返回值。需不需要這個(gè)變量取決于函數(shù)的內(nèi)容。如果函數(shù)有返回值,也就是有 return 語(yǔ)句的話,就需要用一個(gè)變量存儲(chǔ)這個(gè)返回值;反之,如果沒(méi)有返回值,那么就可以直接調(diào)用,不需要變量來(lái)存儲(chǔ)返回值。

如果想要輸出這個(gè)返回的值,或者再使用它進(jìn)行其他一次性操作,也可以不專門用一個(gè)變量存儲(chǔ),而直接把這個(gè)函數(shù)寫(xiě)入進(jìn)行操作的語(yǔ)句中。再拿calc函數(shù)舉例說(shuō)明:

01  def calc(a,b,c):

02    ans=a*b-c

03    return ans

04  print(calc(2,3,4))

運(yùn)行程序,輸出結(jié)果為:

2

這樣,就達(dá)到了簡(jiǎn)化程序的目的。

再來(lái)舉一個(gè)沒(méi)有返回值的函數(shù)的例子:

01  def Output(strArr):

02    for i in range(10):

03     print(strArr[i])

04  Arr=['Apple','Bear','Cat','Dog','Egg','Fruit','Giraffe','Hat','Ice','Jacket']

05  Output(Arr)

運(yùn)行程序,輸出結(jié)果為:

Apple

Bear

Cat

Dog

Egg

Fruit

Giraffe

Hat

Ice

Jacket

1.4.4 全局變量

在之前見(jiàn)到的程序中,子函數(shù)內(nèi)部的變量和子函數(shù)外部的變量完全不相關(guān),所以不必?fù)?dān)心重名的問(wèn)題;子函數(shù)外的語(yǔ)句無(wú)法調(diào)用子函數(shù)內(nèi)部的變量,子函數(shù)內(nèi)部的語(yǔ)句也無(wú)法調(diào)用子函數(shù)外部的變量。這使程序的結(jié)構(gòu)更加清晰,但也帶來(lái)了一些不便:難道想使用外部的數(shù)據(jù)就必須要傳入子函數(shù)中嗎?

全局變量,顧名思義,就是可以讓整個(gè)程序使用的變量。它一般在整個(gè)程序的最開(kāi)始定義,在所有的函數(shù)和語(yǔ)句的上方。如圖1.30所示,局部變量只在函數(shù)的小范圍內(nèi)存在,跳出這個(gè)范圍,局部變量不存在。而全局變量在整個(gè)程序的范圍內(nèi)存在。

圖1.30 全局變量與局部變量

再次用calc函數(shù)舉例說(shuō)明:

01  g=10

02  def calc(a,b,c):

03    ans=a*b-c

04    return ans

05  print(calc(2,3,4))

在這段程序中,g 就是一個(gè)全局變量。在主函數(shù)和自己定義的子函數(shù)之外的所有語(yǔ)句中,都可以像調(diào)用一個(gè)平常變量一般調(diào)用它。但是,在子函數(shù)內(nèi)部時(shí),就要給它多加一條語(yǔ)句:

01 global g

global 的意思是“全球的”,在程序中也可以被理解為“全局的”。在子函數(shù)內(nèi),在變量名前面加上global這條語(yǔ)句用于聲明這是一個(gè)全局變量。有了這條語(yǔ)句,這個(gè)子函數(shù)內(nèi)的所有代碼都可以像各個(gè)子函數(shù)外的代碼一樣調(diào)用這個(gè)變量并對(duì)它進(jìn)行更改,而且更改的結(jié)果也會(huì)在全局范圍內(nèi)保存。與調(diào)用函數(shù)時(shí)傳進(jìn)函數(shù)的變量不同,在函數(shù)內(nèi)更改這些非全局變量并不會(huì)影響它們本來(lái)的值。

1.4.5 函數(shù)的運(yùn)用

我們來(lái)看一個(gè)問(wèn)題:1個(gè)蘋(píng)果2元,1個(gè)菠蘿8元,1個(gè)西瓜10元。1個(gè)盒子1元,它最多能裝下5個(gè)蘋(píng)果或1個(gè)菠蘿或1個(gè)西瓜。編寫(xiě)一個(gè)程序,讓用戶輸入每種水果的購(gòu)買數(shù)量,然后輸出每種水果加上盒子需要多少錢,以及一共要多少錢。

先自己思考一下該怎么做,再來(lái)看下面的代碼。

首先是沒(méi)有使用函數(shù)的解決方法:

然后是使用了函數(shù)的解決方法:

現(xiàn)在,你熟悉子函數(shù)的定義和使用方法了嗎?

根據(jù)圖1.31所示的關(guān)系來(lái)寫(xiě)一個(gè)滿足問(wèn)題要求的程序。

圖1.31 各科分?jǐn)?shù)評(píng)價(jià)

首先,允許用戶輸入數(shù)學(xué)、英語(yǔ)、歷史這三科的考試分?jǐn)?shù),每一科的分?jǐn)?shù)范圍在0~100之間,超出這個(gè)范圍的分?jǐn)?shù)是錯(cuò)誤分?jǐn)?shù),需要重新輸入。第二,對(duì)每一科的分?jǐn)?shù)做出評(píng)價(jià),評(píng)價(jià)標(biāo)準(zhǔn)如圖1.31所示。

第三,按表1.2中規(guī)定的比例折算各科分?jǐn)?shù)并得到總分,總分范圍是0~300。

表1.2 各科折算總分的比例

續(xù)表

第四,按照表1.3中的標(biāo)準(zhǔn),給總分一個(gè)等級(jí)。最后,輸出對(duì)每一門課考試成績(jī)的評(píng)價(jià)、折算完的總分?jǐn)?shù)和總分對(duì)應(yīng)的等級(jí)。分別用5個(gè)子函數(shù)實(shí)現(xiàn)這5個(gè)要求。

表1.3 總分對(duì)應(yīng)等級(jí)

這是一個(gè)比較復(fù)雜的題目,提供的數(shù)據(jù)和條件比較多。先自己思考該怎么做,用紙和筆記錄下自己的思路和計(jì)劃,再動(dòng)手去寫(xiě)代碼。寫(xiě)完代碼后,再對(duì)照書(shū)上的答案驗(yàn)證。記住,不同的代碼也可以實(shí)現(xiàn)相似的功能,書(shū)上的答案僅供參考。

那么,首先來(lái)寫(xiě)出這個(gè)程序的框架:

先定義好所有要使用的子函數(shù)和主函數(shù)。語(yǔ)句next是用來(lái)“跳過(guò)”一個(gè)子函數(shù)的。當(dāng)子函數(shù)內(nèi)部沒(méi)有任何語(yǔ)句時(shí),Python就會(huì)把下一個(gè)子函數(shù)或者主函數(shù)當(dāng)作子函數(shù)內(nèi)部的語(yǔ)句,從而因?yàn)榭s進(jìn)不對(duì)而報(bào)錯(cuò),加上next語(yǔ)句就可以有效地防止這種情況的發(fā)生。同時(shí),根據(jù)子函數(shù)的功能來(lái)判斷它們需要什么值來(lái)完成任務(wù),從而確定括號(hào)內(nèi)的變量。

現(xiàn)在,就把這些子函數(shù)填滿。

到這里,整個(gè)程序就完成了。

看完這兩個(gè)問(wèn)題之后可以發(fā)現(xiàn),如果沒(méi)有注釋的話,沒(méi)有使用函數(shù)的解決方法雖然也不難完成,但是在寫(xiě)完一大段連著的代碼之后很容易混淆代碼的用處。而使用了函數(shù)就可以有效避免這種情況的發(fā)生。所以,使用函數(shù)還可以讓程序變得更有條理。

到這里,第1章就結(jié)束了。在接下來(lái)要學(xué)習(xí)的諸多算法中,將會(huì)大量使用本章講解的語(yǔ)法。在進(jìn)入下一章之前,一定要先熟悉這些語(yǔ)法,可以多做題目來(lái)練習(xí)。如果你覺(jué)得還沒(méi)有弄懂,那就請(qǐng)重新讀一讀本章再繼續(xù)接下來(lái)的學(xué)習(xí)吧!

主站蜘蛛池模板: 昭平县| 南澳县| 庆云县| 绥中县| 垫江县| 晋州市| 金昌市| 沈阳市| 独山县| 禹城市| 莱西市| 泗洪县| 体育| 和硕县| 富民县| 金溪县| 鞍山市| 巫山县| 锦州市| 桃江县| 西丰县| 贵港市| 东至县| 浏阳市| 莱阳市| 阿克陶县| 昭觉县| 清徐县| 惠州市| 香格里拉县| 婺源县| 中方县| 砚山县| 塔城市| 绥芬河市| 双流县| 新疆| 韩城市| 乌鲁木齐市| 汽车| 辽中县|