Python编程核心内容 ---- Function(函数)
什么“大事”呢?下面將要介紹Python編程的核心內(nèi)容之一——函數(shù)。
對(duì)于Python編程,函數(shù)的重要性不言而喻。重要的事情講三遍:函數(shù)實(shí)在是太重要,太關(guān)鍵了。
引入函數(shù)
之前,我們編寫程序遵循的原則:根據(jù)業(yè)務(wù)邏輯從上到下實(shí)現(xiàn)功能,其往往用一長(zhǎng)段代碼來(lái)實(shí)現(xiàn)指定功能,開(kāi)發(fā)過(guò)程中最常見(jiàn)的操作就是粘貼復(fù)制,也就是將之前實(shí)現(xiàn)的代碼塊復(fù)制到現(xiàn)需功能處。這種編程方式雖然可以應(yīng)付一般性問(wèn)題,但是不能對(duì)付大多數(shù)問(wèn)題。這不,下面就來(lái)個(gè)例子。
r1 = 12.3r2 = 9.1r3 = 64.21s1 = 2 * 3.14 * r15 s2 = 2 * 3.14 * r26 s3 = 2 * 3.14 * r3圓是個(gè)神奇的圖形。特別是π,它讓人類陷入無(wú)限的遐想。OK,回歸正題。為了求圓的周長(zhǎng),我們需要引入公式:周長(zhǎng) = 2 * π * r(半徑)。看到這兒,某些讀者可能會(huì)有疑惑:這跟函數(shù)有什么關(guān)系,之前的方式依然適用。是的,這的確是可以的,但這很麻煩,太重復(fù)啦。那如果現(xiàn)在需要把 π 更改為3.1415926535,那該怎么辦呢?難道我們要一個(gè)一個(gè)地去改???Oh,my god!!!這時(shí),我嗅到了函數(shù)的味道。
有了函數(shù),我們就不再每次寫c = 2 * 3.14 * x,而是寫成更有意義的函數(shù)調(diào)用c = perimeter_of_circle(x),而函數(shù)perimeter_of_circle本身只需要寫一次,就可以多次調(diào)用。
Python不但能非常靈活地定義函數(shù),而且本身內(nèi)置了很多有用的函數(shù),可以直接調(diào)用。
是的,函數(shù)最大的優(yōu)點(diǎn):增強(qiáng)代碼的重用性和可讀性。Python中,函數(shù)就是最基本的一種代碼抽象的方式。.
函數(shù)定義
在Python中,函數(shù)有五大要點(diǎn),分別是def、函數(shù)名、函數(shù)體、參數(shù)、返回值,以及兩個(gè)英文版符號(hào),分別是括號(hào)(括號(hào)內(nèi)為參數(shù))和冒號(hào)(:)。
-
def:函數(shù)的關(guān)鍵字,沒(méi)它可不行。
-
函數(shù)名:函數(shù)的名稱,根據(jù)函數(shù)名調(diào)用函數(shù)。
-
函數(shù)體:函數(shù)中進(jìn)行一系列的具體操作。
-
參數(shù):為函數(shù)體提供數(shù)據(jù)。
-
返回值:當(dāng)函數(shù)執(zhí)行完畢后,可以給調(diào)用者返回?cái)?shù)據(jù)。
上述函數(shù)的要點(diǎn)中,最重要的是參數(shù)和返回值。
1.返回值
函數(shù)是一個(gè)功能塊,該功能到底執(zhí)行成功與否,需要通過(guò)返回值來(lái)告知調(diào)用者。
2.參數(shù)
定義函數(shù)時(shí),參數(shù)是一定需要考慮的。Python的函數(shù)定義非常簡(jiǎn)單,但靈活度卻非常大。
對(duì)于函數(shù)的調(diào)用者來(lái)說(shuō),只需要知道如何傳遞正確的參數(shù),以及函數(shù)將返回什么樣的值就夠了,函數(shù)內(nèi)部的復(fù)雜邏輯被封裝起來(lái),調(diào)用者無(wú)需了解。
Python中,參數(shù)類型有:必選參數(shù)、默認(rèn)參數(shù)、可變參數(shù)、關(guān)鍵字參數(shù)和命名關(guān)鍵字參數(shù)。函數(shù)中,參數(shù)定義的順序必須是:必選參數(shù)、默認(rèn)參數(shù)、可變參數(shù)、命名關(guān)鍵字參數(shù)和關(guān)鍵字參數(shù)。
3.空函數(shù)
空函數(shù):什么事也不做,可以用pass語(yǔ)句。既然“一事不做”,那空函數(shù)還有什么用處?實(shí)際上pass可以用來(lái)作為占位符,比如現(xiàn)在還沒(méi)想好怎么寫函數(shù)的代碼,就可以先放一個(gè)pass,讓代碼能運(yùn)行起來(lái)。如此,運(yùn)行代碼程序就不會(huì)出現(xiàn)錯(cuò)誤了。
#空函數(shù) def nop():pass函數(shù)參數(shù)
Python中,參數(shù)是非常靈活的。掌握參數(shù)就能領(lǐng)悟函數(shù)的真諦了。這是真的。參數(shù)是比較難理解的,特別是參數(shù)組合。
1.位置參數(shù)
既然說(shuō)函數(shù),就需要展示函數(shù):
''' 遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:857662006 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書(shū)! ''' #位置參數(shù)(必選參數(shù)) def involution(x):return x * x >>>involution(3) 9 >>>involution(5) 25如代碼所示,參數(shù)x就是一個(gè)位置參數(shù)。
2.默認(rèn)參數(shù)
Python函數(shù)支持默認(rèn)參數(shù),即可以給函數(shù)的參數(shù)指定默認(rèn)值。當(dāng)該參數(shù)沒(méi)有傳入相應(yīng)的值時(shí),該參數(shù)就使用默認(rèn)值。
#默認(rèn)參數(shù) def involution(x,n = 2):s = 1while n > 0:n = n - 1s = s * xreturn s >>>involution(6) 36 >>>involution(5,3) 125如代碼所示,當(dāng)我們調(diào)用involution(5),就相當(dāng)于調(diào)用involution(5,2)。
注:
1.設(shè)置默認(rèn)參數(shù)時(shí),必選參數(shù)在前,默認(rèn)參數(shù)在后,否則Python的解釋器會(huì)報(bào)錯(cuò);
2.定義默認(rèn)參數(shù)要牢記:默認(rèn)參數(shù)必須指向不可變對(duì)象!
''' 遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:857662006 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書(shū)! ''' >>>def add_end(L=[]): ... L.append('END') ... return L ... >>>add_end() ['END'] >>>add_end() ['END','END'] >>>add_end() ['END','END','END']上述代碼展示的是默認(rèn)參數(shù)不為不可變對(duì)象的現(xiàn)象。因此,默認(rèn)參數(shù)必須指向不可變對(duì)象【字符串、None……】。
3.可變參數(shù)
在Python函數(shù)中,還可以定義可變參數(shù)。顧名思義,可變參數(shù)就是傳入的參數(shù)個(gè)數(shù)是可變的,可以是1個(gè)、2個(gè)到任意個(gè),還可以是0個(gè)。
我們以數(shù)學(xué)題為例子,給定一組數(shù)字a,b,c……,請(qǐng)計(jì)算a2 + b2 + c2 + ……。
要定義出這個(gè)函數(shù),我們必須確定輸入的參數(shù)。由于參數(shù)個(gè)數(shù)不確定,我們首先想到可以把a(bǔ),b,c……作為一個(gè)list或tuple傳進(jìn)來(lái),這樣,函數(shù)可以定義如下:
#一般性函數(shù) def calc(numbers):sum = 0for n in numbers:sum = sum + n * nreturn sum如何調(diào)用calc()函數(shù)呢?需要調(diào)用時(shí),需要為參數(shù)引入list或者tuple。
''' 遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:857662006 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書(shū)! ''' #函數(shù)調(diào)用 >>> calc([1, 2, 3]) 14 >>> calc((1, 3, 5, 7)) 84然而,如果我們使用可變參數(shù),我們可以進(jìn)行簡(jiǎn)化,方法如下:
#可變參數(shù) def calc(*numbers):sum = 0for n in numbers:sum = sum + n * nreturn sum咋調(diào)用呢?這個(gè)可簡(jiǎn)單啦,再也不用list或者tuple了。參數(shù)調(diào)用只需如下所示:
#可變參數(shù)的魅力 >>> calc(1, 2, 3) 14 >>> calc(1, 3, 5, 7) 84#參數(shù)調(diào)用不用calc([1,2,3]),括號(hào)內(nèi)還用寫中括號(hào),好麻煩~~~定義可變參數(shù)和定義一個(gè)list或tuple參數(shù)相比,僅僅在參數(shù)前面加了一個(gè)*號(hào)。在函數(shù)內(nèi)部,參數(shù)numbers接收到的是一個(gè)tuple,因此,函數(shù)代碼完全不變。但是,調(diào)用該函數(shù)時(shí),可以傳入任意個(gè)參數(shù),包括0個(gè)參數(shù):
>>> calc(1, 2) 5 >>> calc() 0如果已經(jīng)有一個(gè)list或者tuple,要調(diào)用一個(gè)可變參數(shù)怎么辦?可以這樣做:
>>> nums = [1, 2, 3]>>> calc(nums[0], nums[1], nums[2])14這種寫法當(dāng)然是可行的,問(wèn)題是太繁瑣,所以Python允許你在list或tuple前面加一個(gè)*號(hào),把list或tuple的元素變成可變參數(shù)傳進(jìn)去:
>>> nums = [1, 2, 3]>>> calc(*nums)144.關(guān)鍵字參數(shù)
可變參數(shù)允許你傳入0個(gè)或任意個(gè)參數(shù),這些可變參數(shù)在函數(shù)調(diào)用時(shí)自動(dòng)組裝為一個(gè)tuple。而關(guān)鍵字參數(shù)允許你傳入0個(gè)或任意個(gè)含參數(shù)名的參數(shù),這些關(guān)鍵字參數(shù)在函數(shù)內(nèi)部自動(dòng)組裝為一個(gè)dict。dict就是字典,它是鍵值對(duì)組合,益處多多~~~
#引入關(guān)鍵字參數(shù),默認(rèn)為**kwdef person(name, age, **kw):print('name:', name, 'age:', age, 'other:', kw)函數(shù)person除了必選參數(shù)name和age外,還接受關(guān)鍵字參數(shù)kw。在調(diào)用該函數(shù)時(shí),可以只傳入必選參數(shù)(必選參數(shù)必須全部傳入,否則會(huì)出錯(cuò)),也可以傳入關(guān)鍵字參數(shù)。注:關(guān)鍵字參數(shù)可是任意個(gè)的。
''' 遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:857662006 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書(shū)! ''' #調(diào)用關(guān)鍵字參數(shù) >>>def person(name,age,**kw): ... print('name:',name,'age:',age,'other:',kw) ... >>>person('Jack') Traceback (most recent call last):File "<stdin>", line 1, in <module> TypeError: person() missing 1 required positional argument: 'age' >>>person('Jack',36) name:Jack age:36 other:{} >>>person('Jack',36,city='Hangzhou') name:Jack age:36 other:{'city':'Hangzhou'} >>>person('Jack',36,city='Hangzhou',job='Engineer') name:Jack age:36 other:{'city':'Hangzhou','job':'Engineer'}關(guān)鍵字參數(shù)有什么用呢?其實(shí),既然存在就有它的強(qiáng)大之處。就像自然界中的萬(wàn)物,物競(jìng)天擇,適者生存。如果它能夠在自然界中生存下來(lái),那么它就有獨(dú)特的生存本領(lǐng)。因此,關(guān)鍵字參數(shù)還是有用武之地的。
它可以擴(kuò)展函數(shù)的功能。比如,在person函數(shù)里,我們保證能接收到name和age這兩個(gè)參數(shù),但是,如果調(diào)用者愿意提供更多的參數(shù),我們也能收到。試想你正在做一個(gè)用戶注冊(cè)的功能,除了用戶名和年齡是必填項(xiàng)外,其他都是可選項(xiàng),利用關(guān)鍵字參數(shù)來(lái)定義這個(gè)函數(shù)就能滿足注冊(cè)的需求。
如何操作呢?我們可以先組裝出一個(gè)dict,然后,把該dict轉(zhuǎn)換為關(guān)鍵字參數(shù)傳進(jìn)去:
>>> extra = {'city': 'Hangzhou', 'job': 'Engineer'}>>> person('Jack', 36, city=extra['city'], job=extra['job'])name: Jack age: 36 other: {'city': 'Hangzhou', 'job': 'Engineer'}當(dāng)然了,上面代碼調(diào)用方式有點(diǎn)煩,通過(guò)dict鍵來(lái)查找值。我們可以通過(guò)關(guān)鍵字簡(jiǎn)化一下:
>>> extra = {'city': 'Hangzhou', 'job': 'Engineer'}>>> person('Jack', 36, **extra)name: Jack age: 36 other: {'city': 'Hangzhou', 'job': 'Engineer'}extra表示把extra這個(gè)dict的所有key-value用關(guān)鍵字參數(shù)傳入到函數(shù)的kw參數(shù),kw將獲得一個(gè)dict。
5.命名關(guān)鍵字參數(shù)
對(duì)于關(guān)鍵字參數(shù),函數(shù)的調(diào)用者可以傳入任意不受限制的關(guān)鍵字參數(shù)。至于到底傳入了哪些,就需要在函數(shù)內(nèi)部通過(guò)kw檢查。
仍以person()函數(shù)為例,我們希望檢查是否有city和job參數(shù):
''' 遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:857662006 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書(shū)! ''' def person(name, age, **kw):if 'city' in kw:# 有city參數(shù)passif 'job' in kw:# 有job參數(shù)passprint('name:', name, 'age:', age, 'other:', kw)如果要限制關(guān)鍵字參數(shù)的名字,就可以用命名關(guān)鍵字參數(shù),例如,只接收city和job作為關(guān)鍵字參數(shù)。這種方式定義的函數(shù)如下:
def person(name, age, *, city, job):print(name, age, city, job)和關(guān)鍵字參數(shù)*kw不同,命名關(guān)鍵字參數(shù)需要一個(gè)特殊分隔符,*后面的參數(shù)被視為命名關(guān)鍵字參數(shù)。
調(diào)用命名關(guān)鍵字參數(shù)方式如下:
那如果參數(shù)中有可變參數(shù),那該怎么辦呢?
若可變參數(shù)后面跟著命名關(guān)鍵字參數(shù),后面跟著的命名關(guān)鍵字參數(shù)就不再需要一個(gè)特殊分隔符*了。
def person(name, age, *args, city, job):print(name, age, args, city, job)命名關(guān)鍵字參數(shù)必須傳入?yún)?shù)名,這和位置參數(shù)不同。如果沒(méi)有傳入?yún)?shù)名,調(diào)用將報(bào)錯(cuò)。而命名關(guān)鍵字參數(shù)可以有缺省值,從而簡(jiǎn)化調(diào)用:
def person(name, age, *, city='Hangzhou', job):print(name, age, city, job)由于命名關(guān)鍵字參數(shù)city具有默認(rèn)值,調(diào)用時(shí),可不傳入city參數(shù):
>>> person('Jack', 36, job='Engineer')Jack 36 Hangzhou Engineer6.參數(shù)組合
目前,函數(shù)中共有5種常用的參數(shù)類型。若只傳入一種類型的參數(shù),這太簡(jiǎn)單了。難點(diǎn)在哪?難點(diǎn)就在參數(shù)組合使用,那是相當(dāng)惡心。不過(guò),平時(shí)最好不要混合使用參數(shù),不然容易搞得“烏煙瘴氣”。
OK!言歸正傳,不然跑題啦。
Python中,定義一個(gè)函數(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ù)。
下面來(lái)定義一個(gè)函數(shù),該函數(shù)參數(shù)包含一種或幾種參數(shù)。
def f1(a, b, c=0, *args, **kw):print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)def f2(a, b, c=0, *, d, **kw):print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)在函數(shù)調(diào)用的時(shí)候,Python解釋器自動(dòng)按照參數(shù)位置和參數(shù)名把對(duì)應(yīng)的參數(shù)傳進(jìn)去。
>>> f1(1, 2) a = 1 b = 2 c = 0 args = () kw = {} >>> f1(1, 2, c=3) a = 1 b = 2 c = 3 args = () kw = {} >>> f1(1, 2, 3, 'a', 'b') a = 1 b = 2 c = 3 args = ('a', 'b') kw = {} >>> f1(1, 2, 3, 'a', 'b', x=99) a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99} >>> f2(1, 2, d=99, ext=None) a = 1 b = 2 c = 0 d = 99 kw = {'ext': None}最神奇的是通過(guò)一個(gè)tuple和dict,你也可以調(diào)用上述函數(shù):
''' 遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:857662006 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書(shū)! ''' >>> args = (1, 2, 3, 4) >>> kw = {'d': 99, 'x': '#'} >>> f1(*args, **kw) a = 1 b = 2 c = 3 args = (4,) kw = {'d': 99, 'x': '#'} >>> args = (1, 2, 3) >>> kw = {'d': 88, 'x': '#'} >>> f2(*args, **kw) a = 1 b = 2 c = 3 d = 88 kw = {'x': '#'}所以,對(duì)于任意函數(shù),都可以通過(guò)類似func(*args, **kw)的形式調(diào)用它,無(wú)論它的參數(shù)是如何定義的。
然而,雖然函數(shù)參數(shù)類型多達(dá)5種,但不要同時(shí)使用太多的組合,否則函數(shù)接口的可理解性很差。哎,簡(jiǎn)簡(jiǎn)單單才是真啊。
7.函數(shù)參數(shù)小結(jié)
參數(shù),作為函數(shù)傳入值的媒介,這里有必要做一個(gè)總結(jié)。
一、Python的函數(shù)具有非常靈活的參數(shù)形態(tài),既可以實(shí)現(xiàn)簡(jiǎn)單的調(diào)用,又可以傳入非常復(fù)雜的參數(shù);
二、默認(rèn)參數(shù)一定要用不可變對(duì)象,如果是可變對(duì)象,程序運(yùn)行時(shí)會(huì)有邏輯錯(cuò)誤;
三、*args是可變參數(shù),args接收的是一個(gè)tuple;
四、**kw是關(guān)鍵字參數(shù),kw接收的是一個(gè)dict;
五、可變參數(shù)既可以直接傳入:func(1, 2, 3),又可以先組裝list或tuple,再通過(guò)args傳入:func((1, 2, 3));
六、關(guān)鍵字參數(shù)既可以直接傳入:func(a=1, b=2),又可以先組裝dict,再通過(guò)kw傳入:func({‘a(chǎn)’: 1, ‘b’: 2});
七、使用*args和**kw是Python的習(xí)慣寫法,當(dāng)然也可以用其他參數(shù)名,但最好使用習(xí)慣用法;
八、命名的關(guān)鍵字參數(shù)是為了限制調(diào)用者可以傳入的參數(shù)名,同時(shí)可以提供默認(rèn)值;
九、定義命名的關(guān)鍵字參數(shù)在沒(méi)有可變參數(shù)的情況下不要忘了寫分隔符*,否則定義的將是位置參數(shù)。
故而,為了學(xué)好Python中的函數(shù)部分,參數(shù)不容忽視。
函數(shù)調(diào)用
在學(xué)習(xí)了函數(shù)的定義之后,我們應(yīng)該需要調(diào)用函數(shù),獲取我們想要的數(shù)據(jù)。
如何調(diào)用函數(shù)呢?語(yǔ)法:函數(shù)名(參數(shù))
Python中,大佬們內(nèi)置了許多有點(diǎn)用的函數(shù),而我們只需拿來(lái)就行(這讓我想起了魯迅的“拿來(lái)主義”)。
若要調(diào)用Python中的內(nèi)置函數(shù),我們首先要知道函數(shù)名和參數(shù)。哈哈,又是參數(shù)~~~
比如我想要求某數(shù)的絕對(duì)值。如果你不知道Python有相關(guān)的內(nèi)置函數(shù),就只能這么做:
#求取絕對(duì)值 >>>def abs(num): ... if num >= 0: ... return num ... else: ... return (-num) ... >>>abs(9) 9 >>>abs(0) 0 >>>abs(-8) 8上述代碼雖然可以實(shí)現(xiàn)求絕對(duì)值的功能,但是太繁瑣,需要敲幾行代碼才能實(shí)現(xiàn)該功能。然而,Python中有這個(gè)函數(shù)可以直接調(diào)用并輸出結(jié)果。
#Python內(nèi)置函數(shù):abs() >>>abs(-9) 9 >>>abs(9) 9 #獲取幫助文檔 >>>help(abs) Help on built-in function abs in module builtins:abs(x, /)Return the absolute value of the argument.對(duì)于函數(shù)參數(shù),通常會(huì)遇到以下兩個(gè)問(wèn)題:
1.如果函數(shù)傳入?yún)?shù)的數(shù)量錯(cuò)誤,會(huì)如何呢?簡(jiǎn)單,直接Error唄。比如abs():
#函數(shù)傳入?yún)?shù)的數(shù)量錯(cuò)誤>>> abs(-9,89)Traceback (most recent call last):File "<stdin>", line 1, in <module>TypeError: abs() takes exactly one argument (2 given)2.如果傳入的參數(shù)數(shù)量是對(duì)的,但參數(shù)類型不能被函數(shù)所接受,也會(huì)報(bào)TypeError的錯(cuò)誤,并且給出錯(cuò)誤信息:str是錯(cuò)誤的參數(shù)類型:
#傳入的參數(shù)類型錯(cuò)誤>>> abs('a')Traceback (most recent call last):File "<stdin>", line 1, in <module>TypeError: bad operand type for abs(): 'str'常見(jiàn)內(nèi)置函數(shù)(Built-in Functions)
Python 3.x版本下官方網(wǎng)站:https://docs.python.org/3/library/functions.html。該網(wǎng)址內(nèi)顯示Python內(nèi)置函數(shù)相關(guān)內(nèi)容(Built-in Functions)。
1.數(shù)據(jù)結(jié)構(gòu)相關(guān):list()、tuple()、dict()、str()……
2.數(shù)字相關(guān):abs()、min()、max()、len()……
3.其他:int()、float()……
好,不一一例舉了,直接上圖吧~~~
數(shù)據(jù)類型轉(zhuǎn)換
Python內(nèi)置的常用函數(shù)還包括數(shù)據(jù)類型轉(zhuǎn)換函數(shù),比如int()函數(shù)可以把其他數(shù)據(jù)類型轉(zhuǎn)換為整數(shù):
#Python之?dāng)?shù)據(jù)類型轉(zhuǎn)換(int、float、str……) >>> int('123') 123 >>> int(12.34) 12 >>> float('12.34') 12.34 >>> str(1.23) '1.23' >>> str(100) '100' >>> bool(1) True >>> bool('') False函數(shù)別名
了解Linux的讀者可能知道別名(alias,unalias)這個(gè)指令。Python中也有“別名”之說(shuō),比如把函數(shù)名賦給變量:
#函數(shù)“別名” >>>abs(-8) 8 >>>a = abs >>>a(-9) 9 >>>a(0) 0 >>>a(9) 9遞歸函數(shù)
講述遞歸函數(shù)之前,我想起一個(gè)東西:階乘(n!)。舉個(gè)例子,我們來(lái)計(jì)算階乘n! = 1 x 2 x 3 x … x n,用函數(shù)fact(n)表示,可以看出:
fact(n) = n! = 1 x 2 x 3 x ... x (n-1) x n = (n-1)! x n = fact(n-1) x n因此,遞歸函數(shù):在函數(shù)內(nèi)部,一個(gè)函數(shù)在內(nèi)部調(diào)用自身本身。
于是,fact(n)用遞歸的方式寫出來(lái)就是:
''' 遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:857662006 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書(shū)! ''' #遞歸函數(shù) >>>def fact(n): ... if n == 1: ... return 1 ... else: ... return fact(n - 1) * n ... >>>fact(1) 1 >>>fact(5) 120 #遞歸函數(shù)之棧溢出 >>>fact(1000) Traceback (most recent call last):File "<stdin>", line 1, in <module>File "<stdin>", line 5, in xFile "<stdin>", line 5, in xFile "<stdin>", line 5, in x[Previous line repeated 994 more times]File "<stdin>", line 2, in x RecursionError: maximum recursion depth exceeded in comparison如代碼所示,使用遞歸函數(shù)的優(yōu)點(diǎn)是邏輯簡(jiǎn)單清晰,缺點(diǎn)是過(guò)深的調(diào)用會(huì)導(dǎo)致棧溢出。
針對(duì)尾遞歸優(yōu)化的語(yǔ)言可以通過(guò)尾遞歸防止棧溢出。尾遞歸事實(shí)上和循環(huán)是等價(jià)的,沒(méi)有循環(huán)語(yǔ)句的編程語(yǔ)言只能通過(guò)尾遞歸實(shí)現(xiàn)循環(huán)。
Python標(biāo)準(zhǔn)的解釋器沒(méi)有針對(duì)尾遞歸做優(yōu)化,任何遞歸函數(shù)都存在棧溢出的問(wèn)題。
什么是尾遞歸?這個(gè)請(qǐng)讀者自行查詢唄,這里就不介紹啦,嘿嘿~~~
下面來(lái)個(gè)斐波拉契數(shù)列:
#斐波拉契數(shù)列 >>>def fibo(arg1,arg2): ... if arg1 == 0: ... print(arg1,arg2) ... arg3 = arg1 + arg2 ... print(arg3) ... fibo(arg2, arg3) ... >>>fibo(0,1)上述代碼展示的斐波拉契數(shù)列會(huì)一直計(jì)算,直至棧溢出:
#斐波拉契數(shù)列導(dǎo)致棧溢出 488272859468887457959087733119242564077850743657661180827326798539177758919828135114407499369796465649524266755391104990099120377 Traceback (most recent call last):File "<stdin>", line 1, in <module>File "<stdin>", line 6, in fiboFile "<stdin>", line 6, in fiboFile "<stdin>", line 6, in fibo[Previous line repeated 992 more times]File "<stdin>", line 5, in fibo RecursionError: maximum recursion depth exceeded while calling a Python object 16602747662452097049541800472897701834948051198384828062358553091918573717701170201065510185595898605104094736918879278462233015981029522997836311232618760539199036765399799926731433239718860373345088375054249如何才能避免棧溢出呢?自己想唄,要不大腦會(huì)生銹的。
對(duì)于漢羅塔問(wèn)題,利用遞歸來(lái)解決該問(wèn)題也是相當(dāng)?shù)暮?jiǎn)單,且代碼清晰:
#遞歸解決漢羅塔問(wèn)題 >>>def hanrota(n,a,b,c): ... if n == 1: ... print(a,'-->',c) ... else: ... hanrota(n - 1,a,c,b) ... hanrota(1,a,b,c) ... hanrota(n - 1,b,a,c) ... >>>hanrota(3,'A','B','C') A --> C A --> B C --> B A --> C B --> A B --> C A --> C匿名函數(shù)
定義函數(shù)真得不可多得,但有時(shí)候不需要顯示地定義函數(shù)。因此,函數(shù)也需要靈活地運(yùn)用。使用匿名函數(shù)可以更加方便。
匿名函數(shù)語(yǔ)法:
lambda x: x * x(關(guān)鍵字lambda表示匿名函數(shù),冒號(hào)前面的x表示函數(shù)參數(shù))
def f(x):return x * x匿名函數(shù)的好處:因?yàn)楹瘮?shù)沒(méi)有名字,不必?fù)?dān)心函數(shù)名沖突。
def is_odd(n):return n % 2==1L = list(filter(lambda n: n%2==1,range(1,20)))print(L)1.匿名函數(shù)也是一個(gè)函數(shù)對(duì)象,也可以把匿名函數(shù)賦值給一個(gè)變量,再利用變量來(lái)調(diào)用該函數(shù)。
2.Python中,匿名函數(shù)可以作為返回值返回并輸出結(jié)果。
總結(jié)
以上是生活随笔為你收集整理的Python编程核心内容 ---- Function(函数)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 警告!你的Python代码命名太烂了,命
- 下一篇: python一条语句分析几个常用函数和概