日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

廖雪峰Python教程筆記(三)

系統(tǒng) 2275 0

廖雪峰Python教程筆記(三)

  • 5 函數(shù)

5 函數(shù)

基本上所有的高級(jí)語(yǔ)言都支持函數(shù),Python也不例外。Python不但能非常靈活地定義函數(shù),而且本身內(nèi)置了很多有用的函數(shù),可以直接調(diào)用。

抽象
計(jì)算數(shù)列的和,比如:1 + 2 + 3 + … + 100
在這里插入圖片描述
看到 ∑ 就可以理解成求和
借助抽象,我們才能不關(guān)心底層的具體計(jì)算過(guò)程,而直接在更高的層次上思考問題。

函數(shù)就是最基本的一種代碼抽象的方式。

調(diào)用函數(shù)
要調(diào)用一個(gè)函數(shù),需要知道函數(shù)的名稱和參數(shù),比如求絕對(duì)值的函數(shù)abs
廖雪峰Python教程筆記(三)_第1張圖片
調(diào)用函數(shù)的時(shí)候,如果傳入的參數(shù)數(shù)量不對(duì),會(huì)報(bào)TypeError的錯(cuò)誤:
abs() takes exactly one argument (2 given)

果傳入的參數(shù)數(shù)量是對(duì)的,但參數(shù)類型不能被函數(shù)所接受,也會(huì)報(bào)TypeError的錯(cuò)誤:
bad operand type for abs(): ‘str’

而max函數(shù)max()可以接收任意多個(gè)參數(shù),并返回最大的那個(gè):
廖雪峰Python教程筆記(三)_第2張圖片
數(shù)據(jù)類型轉(zhuǎn)換
比如int()函數(shù)可以把其他數(shù)據(jù)類型轉(zhuǎn)換為整數(shù):
廖雪峰Python教程筆記(三)_第3張圖片
函數(shù)名其實(shí)就是指向一個(gè)函數(shù)對(duì)象的引用,完全可以把函數(shù)名賦給一個(gè)變量,相當(dāng)于給這個(gè)函數(shù)起了一個(gè)“別名”:
在這里插入圖片描述

定義函數(shù) ;在Python中,定義一個(gè)函數(shù)要使用def語(yǔ)句,依次寫出函數(shù)名、括號(hào)、括號(hào)中的參數(shù)和冒號(hào):然后,在縮進(jìn)塊中編寫函數(shù)體,函數(shù)的返回值用return語(yǔ)句返回。
以自定義一個(gè)求絕對(duì)值的my_abs函數(shù)為例:
廖雪峰Python教程筆記(三)_第4張圖片

函數(shù)體內(nèi)部的語(yǔ)句在執(zhí)行時(shí),一旦執(zhí)行到return時(shí),函數(shù)就執(zhí)行完畢,并將結(jié)果返回。因此,函數(shù)內(nèi)部 通過(guò)條件判斷和循環(huán)可以實(shí)現(xiàn)非常復(fù)雜的邏輯

如果沒有return語(yǔ)句,函數(shù)執(zhí)行完畢后也會(huì)返回結(jié)果,只是結(jié)果為None。return None可以簡(jiǎn)寫為return。

空函數(shù)
如果想定義一個(gè)什么事也不做的空函數(shù),可以用pass語(yǔ)句:
在這里插入圖片描述
pass語(yǔ)句什么都不做,那有什么用?實(shí)際上pass可以用來(lái)作為占位符,比如現(xiàn)在還沒想好怎么寫函數(shù)的代碼,就可以 先放一個(gè)pass,讓代碼能運(yùn)行起來(lái)。

參數(shù)檢查
調(diào)用函數(shù)時(shí),如果參數(shù)個(gè)數(shù)不對(duì),Python解釋器會(huì)自動(dòng)檢查出來(lái),并拋出TypeError:
但是如果參數(shù)類型不對(duì),Python解釋器就無(wú)法幫我們檢查。試試my_abs和內(nèi)置函數(shù)abs的差別:
廖雪峰Python教程筆記(三)_第5張圖片
傳入了不恰當(dāng)?shù)膮?shù)時(shí),內(nèi)置函數(shù)abs會(huì)檢查出參數(shù)錯(cuò)誤,而我們定義的my_abs沒有參數(shù)檢查,會(huì)導(dǎo)致if語(yǔ)句出錯(cuò),出錯(cuò)信息和abs不一樣。所以,這個(gè)函數(shù)定義不夠完善。

讓我們修改一下my_abs的定義,對(duì)參數(shù)類型做檢查,只允許整數(shù)和浮點(diǎn)數(shù)類型的參數(shù)。數(shù)據(jù)類型檢查可以用內(nèi)置函數(shù)isinstance()實(shí)現(xiàn):
廖雪峰Python教程筆記(三)_第6張圖片
添加了參數(shù)檢查后,如果傳入錯(cuò)誤的參數(shù)類型,函數(shù)就可以拋出一個(gè)錯(cuò)誤:
廖雪峰Python教程筆記(三)_第7張圖片
TypeError: bad operand type
錯(cuò)誤和異常處理將在后續(xù)講到。

返回多個(gè)值
函數(shù)可以返回多個(gè)值嗎?答案是肯定的。
比如在游戲中經(jīng)常需要從一個(gè)點(diǎn)移動(dòng)到另一個(gè)點(diǎn),給出坐標(biāo)、位移和角度,就可以計(jì)算出新的坐標(biāo):
廖雪峰Python教程筆記(三)_第8張圖片
import math語(yǔ)句表示導(dǎo)入math包,并允許后續(xù)代碼引用math包里的sin、cos等函數(shù)。
廖雪峰Python教程筆記(三)_第9張圖片
這只是一種假象,Python函數(shù)返回的仍然是單一值:原來(lái)返回值是一個(gè)tuple
廖雪峰Python教程筆記(三)_第10張圖片
小結(jié):
1.定義函數(shù)時(shí),需要確定函數(shù)名和參數(shù)個(gè)數(shù);
2.如果有必要,可以先對(duì)參數(shù)的數(shù)據(jù)類型做檢查;
3.函數(shù)體內(nèi)部可以用return隨時(shí)返回函數(shù)結(jié)果;
4.函數(shù)執(zhí)行完畢也沒有return語(yǔ)句時(shí),自動(dòng)return None。
5.函數(shù)可以同時(shí)返回多個(gè)值,但其實(shí)就是一個(gè)tuple。
廖雪峰Python教程筆記(三)_第11張圖片

**函數(shù)的參數(shù):**除了正常定義的必選參數(shù)外,還可以使用默認(rèn)參數(shù)、可變參數(shù)和關(guān)鍵字參數(shù),使得函數(shù)定義出來(lái)的接口,不但能處理復(fù)雜的參數(shù),還可以簡(jiǎn)化調(diào)用者的代碼。

位置參數(shù)
一個(gè)計(jì)算x2的函數(shù):
在這里插入圖片描述
對(duì)于power(x)函數(shù),參數(shù)x就是一個(gè)位置參數(shù)。
當(dāng)我們調(diào)用power函數(shù)時(shí),必須傳入有且僅有的一個(gè)參數(shù)x:
在這里插入圖片描述
如果要計(jì)算x4、x5……怎么辦?我們不可能定義無(wú)限多個(gè)函數(shù)。
可以把power(x)修改為power(x, n),用來(lái)計(jì)算xn,說(shuō)干就干:
廖雪峰Python教程筆記(三)_第12張圖片
修改后的power(x, n)函數(shù)有兩個(gè)參數(shù):x和n,這兩個(gè)參數(shù)都是位置參數(shù),調(diào)用函數(shù)時(shí),傳入的兩個(gè)值按照位置順序依次賦給參數(shù)x和n。

默認(rèn)參數(shù)
新的power(x, n)函數(shù)定義沒有問題,但是,舊的調(diào)用代碼失敗了,原因是我們?cè)黾恿艘粋€(gè)參數(shù),導(dǎo)致舊的代碼因?yàn)槿鄙僖粋€(gè)參數(shù)而無(wú)法正常調(diào)用:
TypeError: power() missing 1 required positional argument: ‘n’

這個(gè)時(shí)候,默認(rèn)參數(shù)就排上用場(chǎng)了。由于我們經(jīng)常計(jì)算x2,所以,完全可以把第二個(gè)參數(shù)n的默認(rèn)值設(shè)定為2:
廖雪峰Python教程筆記(三)_第13張圖片
這樣,當(dāng)我們調(diào)用power(5)時(shí),相當(dāng)于調(diào)用power(5, 2):
廖雪峰Python教程筆記(三)_第14張圖片
設(shè)置默認(rèn)參數(shù)時(shí),有幾點(diǎn)要注意:
一是必選參數(shù)在前,默認(rèn)參數(shù)在后,否則Python的解釋器會(huì)報(bào)錯(cuò)
二是如何設(shè)置默認(rèn)參數(shù)。
當(dāng)函數(shù)有多個(gè)參數(shù)時(shí),把變化大的參數(shù)放前面,變化小的參數(shù)放后面。變化小的參數(shù)就可以作為默認(rèn)參數(shù)。
使用默認(rèn)參數(shù)有什么好處?最大的好處是能降低調(diào)用函數(shù)的難度。

一年級(jí)小學(xué)生注冊(cè)的函數(shù),需要傳入name和gender兩個(gè)參數(shù):
在這里插入圖片描述
廖雪峰Python教程筆記(三)_第15張圖片
如果要繼續(xù)傳入年齡、城市等信息怎么辦?這樣會(huì)使得調(diào)用函數(shù)的復(fù)雜度大大增加。

我們可以把年齡和城市設(shè)為默認(rèn)參數(shù):
廖雪峰Python教程筆記(三)_第16張圖片
廖雪峰Python教程筆記(三)_第17張圖片
只有與默認(rèn)參數(shù)不符的學(xué)生才需要提供額外的信息。

默認(rèn)參數(shù)有個(gè)最大的坑,演示如下:
先定義一個(gè)函數(shù),傳入一個(gè)list,添加一個(gè)END再返回:
在這里插入圖片描述
ZZZZZZZZZZZ
再次調(diào)用add_end()時(shí),結(jié)果就不對(duì)了:
在這里插入圖片描述
Python函數(shù)在定義的時(shí)候,默認(rèn)參數(shù)L的值就被計(jì)算出來(lái)了,即[],因?yàn)槟J(rèn)參數(shù)L也是一個(gè)變量,它指向?qū)ο骩],每次調(diào)用該函數(shù),如果改變了L的內(nèi)容,則下次調(diào)用時(shí),默認(rèn)參數(shù)的內(nèi)容就變了,不再是函數(shù)定義時(shí)的[]了。
在這里插入圖片描述
在這里插入圖片描述 無(wú)論調(diào)用多少次,都不會(huì)有問題:

可變參數(shù)
以數(shù)學(xué)題為例子,給定一組數(shù)字a,b,c……,請(qǐng)計(jì)算a2 + b2 + c2 + ……。
廖雪峰Python教程筆記(三)_第18張圖片
廖雪峰Python教程筆記(三)_第19張圖片
所以,我們把函數(shù)的參數(shù)改為可變參數(shù):
廖雪峰Python教程筆記(三)_第20張圖片
定義可變參數(shù)和定義一個(gè)list或tuple參數(shù)相比,僅僅在參數(shù)前面加了一個(gè)*號(hào)。在函數(shù)內(nèi)部,參數(shù)numbers接收到的是一個(gè)tuple,因此,函數(shù)代碼完全不變。
在這里插入圖片描述
廖雪峰Python教程筆記(三)_第21張圖片

*nums表示把nums這個(gè)list的所有元素作為可變參數(shù)傳進(jìn)去。這種寫法相當(dāng)有用,而且很常見。

關(guān)鍵字參數(shù)
關(guān)鍵字參數(shù)允許你傳入0個(gè)或任意個(gè)含參數(shù)名的參數(shù),這些關(guān)鍵字參數(shù)在函數(shù)內(nèi)部自動(dòng)組裝為一個(gè)dict。
在這里插入圖片描述
函數(shù)person除了必選參數(shù)name和age外,還接受關(guān)鍵字參數(shù)kw。在調(diào)用該函數(shù)時(shí),可以只傳入必選參數(shù):
在這里插入圖片描述
也可以傳入任意個(gè)數(shù)的關(guān)鍵字參數(shù):
在這里插入圖片描述

命名關(guān)鍵字參數(shù)
對(duì)于關(guān)鍵字參數(shù),函數(shù)的調(diào)用者可以傳入任意不受限制的關(guān)鍵字參數(shù)。至于到底傳入了哪些,就需要在函數(shù)內(nèi)部通過(guò)kw檢查。

仍以person()函數(shù)為例,我們希望檢查是否有city和job參數(shù):
廖雪峰Python教程筆記(三)_第22張圖片
但是調(diào)用者仍可以傳入不受限制的關(guān)鍵字參數(shù):
在這里插入圖片描述

參數(shù)組合
在Python中定義函數(shù),可以用必選參數(shù)、默認(rèn)參數(shù)、可變參數(shù)、關(guān)鍵字參數(shù)和命名關(guān)鍵字參數(shù),這5種參數(shù)都可以組合使用。但是請(qǐng)注意,參數(shù)定義的順序必須是:必選參數(shù)、默認(rèn)參數(shù)、可變參數(shù)、命名關(guān)鍵字參數(shù)和關(guān)鍵字參數(shù)。

比如定義一個(gè)函數(shù),包含上述若干種參數(shù):

廖雪峰Python教程筆記(三)_第23張圖片
廖雪峰Python教程筆記(三)_第24張圖片

函數(shù)調(diào)用:
在函數(shù)內(nèi)部,可以調(diào)用其他函數(shù)。如果一個(gè)函數(shù)在內(nèi)部調(diào)用自身本身,這個(gè)函數(shù)就是遞歸函數(shù)。
計(jì)算階乘n! = 1 x 2 x 3 x … x n
在這里插入圖片描述
廖雪峰Python教程筆記(三)_第25張圖片

遞歸函數(shù)的優(yōu)點(diǎn)是定義簡(jiǎn)單,邏輯清晰。 理論上,所有的遞歸函數(shù)都可以寫成循環(huán)的方式,但循環(huán)的邏輯不如遞歸清晰。

使用遞歸函數(shù)需要注意防止棧溢出。 在計(jì)算機(jī)中,函數(shù)調(diào)用是通過(guò)棧(stack)這種數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)的,每當(dāng)進(jìn)入一個(gè)函數(shù)調(diào)用,棧就會(huì)加一層棧幀,每當(dāng)函數(shù)返回,棧就會(huì)減一層棧幀 。由于棧的大小不是無(wú)限的,所以,遞歸調(diào)用的次數(shù)過(guò)多,會(huì)導(dǎo)致棧溢出。可以試試fact(1000):
RuntimeError: maximum recursion depth exceeded in comparison

解決遞歸調(diào)用棧溢出的方法是通過(guò) 尾遞歸優(yōu)化 ,事實(shí)上尾遞歸和循環(huán)的效果是一樣的,所以,把循環(huán)看成是一種特殊的尾遞歸函數(shù)也是可以的。

上面的fact(n)函數(shù)由于return n * fact(n - 1)引入了乘法表達(dá)式,所以就不是尾遞歸了。要改成尾遞歸方式,需要多一點(diǎn)代碼,主要是要把每一步的乘積傳入到遞歸函數(shù)中:
廖雪峰Python教程筆記(三)_第26張圖片
fact(5)對(duì)應(yīng)的fact_iter(5, 1)的調(diào)用如下:
廖雪峰Python教程筆記(三)_第27張圖片

小結(jié)

使用遞歸函數(shù)的優(yōu)點(diǎn)是邏輯簡(jiǎn)單清晰,缺點(diǎn)是過(guò)深的調(diào)用會(huì)導(dǎo)致棧溢出。
針對(duì)尾遞歸優(yōu)化的語(yǔ)言可以通過(guò)尾遞歸防止棧溢出。尾遞歸事實(shí)上和循環(huán)是等價(jià)的,沒有循環(huán)語(yǔ)句的編程語(yǔ)言只能通過(guò)尾遞歸實(shí)現(xiàn)循環(huán)。
Python標(biāo)準(zhǔn)的解釋器沒有針對(duì)尾遞歸做優(yōu)化,任何遞歸函數(shù)都存在棧溢出的問題。


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 邛崃市| 边坝县| 随州市| 偏关县| 图木舒克市| 百色市| 陆丰市| 虎林市| 香格里拉县| 庆元县| 丹东市| 抚顺市| 右玉县| 类乌齐县| 闽侯县| 江华| 巧家县| 塔河县| 临西县| 汤原县| 寿光市| 惠州市| 兴化市| 泰兴市| 诸暨市| 巴塘县| 漳浦县| 麻栗坡县| 泰顺县| 瑞金市| 土默特左旗| 习水县| 民权县| 丹棱县| 拉萨市| 定远县| 星座| 长泰县| 海盐县| 石柱| 武宣县|