日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

python进行linux编程,Python之函数进阶

發(fā)布時(shí)間:2025/3/20 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python进行linux编程,Python之函数进阶 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本節(jié)內(nèi)容

遞歸函數(shù)

嵌套函數(shù)與閉包

匿名函數(shù)

高階函數(shù)

內(nèi)置函數(shù)

總結(jié)

一、遞歸函數(shù)

函數(shù)是可以被調(diào)用的,且一個(gè)函數(shù)內(nèi)部可以調(diào)用其他函數(shù)。如果一個(gè)函數(shù)在內(nèi)部調(diào)用本身,這個(gè)函數(shù)就是一個(gè)遞歸函數(shù)。函數(shù)遞歸調(diào)用的過(guò)程與循環(huán)相似,而且理論上,所有的遞歸函數(shù)都可以寫(xiě)成循環(huán)的方式,但是遞歸函數(shù)的優(yōu)點(diǎn)是定義簡(jiǎn)單,邏輯清晰。遞歸和循環(huán)都是一個(gè)重復(fù)的操作的過(guò)程,這些重復(fù)性的操作必然是需要有一定的規(guī)律性的。另外,很明顯遞歸函數(shù)也需要一個(gè)結(jié)束條件,否則就會(huì)像死循環(huán)一樣遞歸下去,直到由于棧溢出而被終止(這個(gè)下面介紹)。

可見(jiàn),要實(shí)現(xiàn)一個(gè)遞歸函數(shù)需要確定兩個(gè)要素:

遞歸規(guī)律

結(jié)束條件

1. 實(shí)例:計(jì)算正整數(shù)n的階乘 n! = 1 * 2 * 3 * ... * n

循環(huán)實(shí)現(xiàn)

思路有兩個(gè):

從1乘到n,需要額外定義一個(gè)計(jì)數(shù)器存放n當(dāng)前的值

從n乘到1,無(wú)需額外定義計(jì)數(shù)器,直接對(duì)n進(jìn)行減1操作,直到n=0返回1結(jié)束

def fact(n):

if n == 0:

return 1

result = 1

while n >= 1:

result *= n

n -= 1

return result

遞歸實(shí)現(xiàn)

先來(lái)確定遞歸函數(shù)的兩個(gè)要素:

遞歸規(guī)律:n!=1 * 2 * 3 * ... * n = (n-1)! * n,也就是說(shuō)fact(n) = fact(n-1) * n,且n逐一減小

結(jié)束條件:當(dāng)n==0時(shí)返回1結(jié)束

def fact(n):

if n == 0:

return 1

return fact(n-1) * n

怎么樣?遞歸函數(shù)的實(shí)現(xiàn)方式是不是既簡(jiǎn)單、又清晰。

我們計(jì)算fact(5)的計(jì)算過(guò)程是這樣的:

===> fact(5)

===> 5 * fact(4)

===> 5 * (4 * fact(3))

===> 5 * (4 * (3 * fact(2)))

===> 5 * (4 * (3 * (2 * fact(1))))

===> 5 * (4 * (3 * (2 * 1)))

===> 5 * (4 * (3 * 2))

===> 5 * (4 * 6)

===> 5 * 24

===> 120

同理,要實(shí)現(xiàn)求1 + 2 + 3 + ... + n,可以這樣寫(xiě):

def fact(n):

if n == 1:

return 1

return fact(n-1) + n

2. 遞歸函數(shù)優(yōu)缺點(diǎn)

遞歸函數(shù)的優(yōu)點(diǎn):

定義簡(jiǎn)單、邏輯清晰。

遞歸函數(shù)的缺點(diǎn):

效率并不高且需要注意防止棧溢出。

其他特點(diǎn):

大家會(huì)發(fā)現(xiàn)上面實(shí)現(xiàn)的遞歸函數(shù)在運(yùn)算的過(guò)程中n是逐漸減小的,也就是說(shuō)問(wèn)題規(guī)模應(yīng)該是逐層減少的。

3. 遞歸特性總結(jié)

下面我們來(lái)總結(jié)寫(xiě)遞歸的特性:

必須有一個(gè)明確的結(jié)束條件

每次進(jìn)入更深一層的遞歸時(shí),問(wèn)題規(guī)模相比上次遞歸都應(yīng)有所減少

遞歸效率不高,遞歸層次過(guò)多會(huì)導(dǎo)致棧溢出。

因?yàn)樵谟?jì)算中,函數(shù)調(diào)用時(shí)通過(guò)棧(stack,特點(diǎn)是后進(jìn)先出--LIFO)這種數(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)致棧溢出。關(guān)于堆棧的介紹可以看下這里:<>。

每種編程語(yǔ)言都對(duì)遞歸函數(shù)可遞歸的深度有限制(可以看看這里),有些是跟相應(yīng)內(nèi)存空間的分配有關(guān)(因?yàn)闂J窃趦?nèi)存空間中的),如Java。Python中對(duì)遞歸的深度限制默認(rèn)為1000,可以通過(guò)sys.getrecursionlimit()函數(shù)來(lái)獲取該值,超過(guò)這個(gè)深度會(huì)報(bào)錯(cuò):RecursionError: maximum recursion depth exceeded in comparison。當(dāng)然也可以通過(guò)sys.setrecursionlimit(n)來(lái)設(shè)置新的限制值。

二、嵌套函數(shù)與閉包

1. 嵌套函數(shù)

嵌套函數(shù)是指在函數(shù)內(nèi)部定義一個(gè)函數(shù),這些函數(shù)都遵循各自的作用域和生命周期規(guī)則。

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

def outer():

level = 1

print('outer', level)

def inner():

print('inner', level)

inner()

調(diào)用outer函數(shù)outer(),輸出結(jié)果如下:

outer 1

inner 1

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

def outer():

level = 1

print('outer', level)

def inner():

level = 2

print('inner', level)

inner()

調(diào)用outer函數(shù)outer(),輸出結(jié)果如下:

outer 1

inner 2

嵌套函數(shù)查找變量的順序是:先查找自己函數(shù)體內(nèi)部是否包含該變量,如果包含則直接應(yīng)用,如果不包含則查找外層函數(shù)體內(nèi)是否包含該函數(shù),依次向外。

2. 閉包

首先要說(shuō)明一個(gè)問(wèn)題:函數(shù)名其實(shí)也是一個(gè)變量,我們通過(guò)def定義一個(gè)函數(shù)時(shí),實(shí)際上就是在定義一個(gè)變量,函數(shù)名就是變量名稱(chēng),函數(shù)體就是該變量的值。我們知道,變量是可以賦值給其他變量的,因此函數(shù)也是可以被當(dāng)做返回值返回的,并且可以賦值給其他變量。

def outer(x):

def inner(y):

print(x+y)

return inner

f1 = outer(10)

f2 = outer(20)

f1(100)

f2(100)

上面操作的執(zhí)行結(jié)果是:

110

120

我們知道局部變量的作用域是在定義它的函數(shù)體內(nèi)部,局部變量在函數(shù)執(zhí)行時(shí)進(jìn)行聲明,函數(shù)執(zhí)行完畢則會(huì)被釋放。上面也提到過(guò)了,函數(shù)也是一個(gè)變量,那么嵌套函數(shù)內(nèi)部定義的函數(shù)也是一個(gè)局部變量,也就是說(shuō)嵌套函數(shù)每調(diào)用一次,其內(nèi)部的函數(shù)都會(huì)被定義一次。因此,在上面的示例中

f1 = outer(10)

f2 = outer(20)

對(duì)于f1和f2而言,兩次調(diào)用嵌套函數(shù)outer并返回的內(nèi)部函數(shù)inner是不同的,且它們?nèi)〉降膞值也是不同的。從表面上來(lái)看f1和f2相當(dāng)于把x分別替換成了10和20:

def f1(y):

print(10+y)

def f2(y):

print(20+y)

但實(shí)際上不是這樣的,f1和f2還是這樣的:

def f1(y):

print(x+y)

def f2(y):

print(x+y)

f1和f2被調(diào)用時(shí),y的值是通過(guò)參數(shù)傳遞進(jìn)來(lái)的(100),而x還是個(gè)變量。inner函數(shù)會(huì)在自己的函數(shù)體內(nèi)部查找該局部變量x,發(fā)現(xiàn)沒(méi)找到,然后去查找它外層的函數(shù)局部��量x,找到了。這里好像出現(xiàn)問(wèn)題了,因?yàn)橹罢f(shuō)過(guò)了局部變量會(huì)在函數(shù)執(zhí)行結(jié)束后被釋放,那么f1和f2被調(diào)用時(shí)outer函數(shù)已經(jīng)執(zhí)行完了,理論上x(chóng)的值應(yīng)該被釋放了才對(duì)啊,為什么還能引用x的值?其實(shí),這就是閉包的作用。

閉包的定義

如果在一個(gè)內(nèi)部函數(shù)中,引用了外部非全局作用域中的變量,那么這個(gè)內(nèi)部函數(shù)就被認(rèn)為是閉包(closure)。

在一些語(yǔ)言中,在函數(shù)中可以(嵌套)定義另一個(gè)函數(shù)時(shí),如果內(nèi)部的函數(shù)應(yīng)用了外部函數(shù)的變量,則可能產(chǎn)生閉包。閉包可以用來(lái)在一個(gè)函數(shù)與一組“私有”變量之間創(chuàng)建關(guān)聯(lián)關(guān)系。在該內(nèi)部函數(shù)被多次調(diào)用的過(guò)程中,這些私有變量能夠保持其持久性。在支持將函數(shù)作為對(duì)象使用的編程語(yǔ)言中,一般都支持閉包,比如:Python、PHP、Javascript等。

閉包就是根據(jù)不同的配置信息得到不同的結(jié)果。專(zhuān)業(yè)解釋是:閉包(closure)是詞法閉包(Lexical Closure)的簡(jiǎn)稱(chēng),是引用了自由變量的函數(shù)。這個(gè)被引用的自由變量將和這個(gè)函數(shù)一同存在,即使已經(jīng)離開(kāi)了創(chuàng)造它的環(huán)境也不例外。所以,有另一種說(shuō)法認(rèn)為閉包是由函數(shù)和與其相關(guān)的應(yīng)用環(huán)境組合而成的實(shí)體。

閉包的工作原理

Ptyhon支持一種特性叫做函數(shù)閉包(function closres),它的工作原理是:在非全局(global)作用域(函數(shù))中定義inner函數(shù)時(shí),這個(gè)inner函數(shù)會(huì)記錄下外層函數(shù)的namespaces(外層函數(shù)作用域的locals,其中包括外層函數(shù)局部作用域中的所有變量),可以稱(chēng)作:定義時(shí)狀態(tài),inner函數(shù)可以通過(guò)__closure__(早期版本中為func_closure)這個(gè)屬性來(lái)獲得inner函數(shù)外層嵌套函數(shù)的namespaces。其實(shí)我們可以通過(guò)打印一個(gè)函數(shù)的__closesure__屬性值是否為None來(lái)判斷閉包是否發(fā)生。

閉包與裝飾器

其實(shí)裝飾器就是一種閉包,或者說(shuō)裝飾器是閉包的一種經(jīng)典應(yīng)用。區(qū)別在于,裝飾器的參數(shù)(配置信息)是一個(gè)函數(shù)或類(lèi),專(zhuān)門(mén)對(duì)類(lèi)或函數(shù)進(jìn)行加工、處理和功能增強(qiáng)。關(guān)于裝飾器,我們會(huì)在后面詳細(xì)介紹。

三、匿名函數(shù)

在Python中有兩種定義函數(shù)的方式:

通過(guò)def關(guān)鍵字定義的函數(shù):這是最常用的方式,前面已經(jīng)介紹過(guò)

通過(guò)lambda關(guān)鍵字定義的匿名函數(shù):這是本次要說(shuō)的主角

lambda作為一個(gè)關(guān)鍵字,作為引入表達(dá)式的語(yǔ)法。與def定義的函數(shù)相比較而言,lambda是單一的表達(dá)式,而不是語(yǔ)句塊。也就是說(shuō),我們僅僅能夠在lambda中封裝有限的業(yè)務(wù)邏輯(通常只是一個(gè)表達(dá)式),這樣設(shè)計(jì)的目的在于:讓lambda純粹為了編寫(xiě)簡(jiǎn)單的函數(shù)(通常稱(chēng)為小函數(shù))而設(shè)計(jì),def則專(zhuān)注于處理更大的業(yè)務(wù)。

1. 匿名函數(shù)的定義

語(yǔ)法:

lambda argument1, argument2, ... argumentN :expression using argments

冒號(hào)左邊是函數(shù)的參數(shù),冒號(hào)右邊是一個(gè)整合參數(shù)并計(jì)算返回值的表達(dá)式。

實(shí)例:定義一個(gè)求兩個(gè)數(shù)之和的函數(shù)

def函數(shù)

def add(x, y):

return x + y

lambda函數(shù)

lambda x, y: x+y

2. 匿名函數(shù)的調(diào)用方式:

調(diào)用方式1:匿名函數(shù)也是一個(gè)函數(shù)對(duì)象,可以將匿名函數(shù)賦值給一個(gè)變量,然后通過(guò)在這個(gè)變量后加上一對(duì)小括號(hào)來(lái)調(diào)用:

add = lambda x, y: x+y

sum = add(1, 2)

調(diào)用方式2:直接在lambda函數(shù)后加上一堆小括號(hào)調(diào)用:

sum = (lambda x, y: x+y)(1, 3)

3. 匿名函數(shù)的特性:

函數(shù)體只能包含一個(gè)表達(dá)式

不能有return語(yǔ)句(表達(dá)式的值就是它的返回值)

參數(shù)個(gè)數(shù)不限,可以有0個(gè)、1個(gè)或多個(gè)

4. 什么時(shí)候用匿名函數(shù)

從上面提到的“匿名函數(shù)的調(diào)用方式”來(lái)看,匿名函數(shù)貌似沒(méi)有什么卵用,反而可讀性更差了。那么匿名函數(shù)在Python中存在的意義是什么呢?匿名函數(shù)一般應(yīng)用于函數(shù)式編程中,在Python中通常是指與高階函數(shù)的配合使用--把匿名函數(shù)當(dāng)做高階函數(shù)的參數(shù)來(lái)使用,下面的高階函數(shù)實(shí)例中會(huì)用到。

四、高階函數(shù)

我們上面已經(jīng)提到過(guò):函數(shù)名也是變量,函數(shù)名就是指向函數(shù)的變量。并且我們已經(jīng)知道:變量是可以作為參數(shù)傳遞給函數(shù)的。由此,我們得出一個(gè)結(jié)論:函數(shù)是一個(gè)接受另外一個(gè)函數(shù)作為參數(shù)的,而這種函數(shù)就稱(chēng)為高階函數(shù)(Higher-order function)。

1. 自定義高階函數(shù)

我們來(lái)自定義一個(gè)高階函數(shù),這個(gè)函數(shù)用于求兩個(gè)數(shù)的和,同時(shí)接收一個(gè)函數(shù)用于在求和之前對(duì)兩個(gè)數(shù)值參數(shù)做一些額外的處理(如:取絕對(duì)值、求平方或其他任意操作)

def nb_add(x, y, f):

return f(x) + f(y)

其中x,y是用于求和的兩個(gè)數(shù)值參數(shù),f是對(duì)x,y進(jìn)行處理的函數(shù)。我們?cè)囍冉of傳遞一個(gè)內(nèi)置的abs(取絕對(duì)值)函數(shù),也就是說(shuō)先對(duì)x和y分別取絕對(duì)值,然后再相加:

result = nb_add(10, -20, abs)

print(result)

運(yùn)行結(jié)果是:30

我們來(lái)自定義一個(gè)求平方的方法,然后傳遞給f試試:

def pow2(x):

return pow(x, 2)

result = nb_add(10, -20, pow2)

print(result)

輸出結(jié)果是:500

我們發(fā)現(xiàn)上面定義的pow2(x)函數(shù)的函數(shù)體只有一個(gè)表達(dá)式,因此我們完全可以不單獨(dú)定義該函數(shù)而使用匿名函數(shù)來(lái)實(shí)現(xiàn),這樣可以使diamante變得更簡(jiǎn)潔:

def nb_add(x, y, f):

return f(x) + f(y)

result = nb_add(10, 20, lambda x: pow(x, 2))

print(result)

2. 常見(jiàn)內(nèi)置高階函數(shù)

Python內(nèi)置了一些非常有用的高階函數(shù),下面我們來(lái)看看常見(jiàn)的幾個(gè):

map函數(shù)

map(function, iterable, ...)

map函數(shù)的參數(shù)說(shuō)明:

map函數(shù)接收兩類(lèi)參數(shù):函數(shù)和可迭代對(duì)象(Iterable)

第一個(gè)參數(shù)是函數(shù),后面的參數(shù)都是可迭代對(duì)象。

處理函數(shù)的參數(shù)個(gè)數(shù)需要與傳入的可迭代對(duì)象參數(shù)的個(gè)數(shù)對(duì)應(yīng),否則會(huì)報(bào)錯(cuò)。

如果傳入的可迭代對(duì)象參數(shù)有多個(gè),且每個(gè)iterable元素?cái)?shù)量不相等時(shí),結(jié)果中的元素個(gè)數(shù)與最短的那個(gè)iterable的元素個(gè)數(shù)一致。

map函數(shù)的作用是:

將傳入的函數(shù)依次作用到可迭代對(duì)象的每個(gè)元素,并把結(jié)果作為新的迭代器對(duì)象(Iterator)返回(Python2.x中會(huì)直接返回一個(gè)列表)。

實(shí)例1:計(jì)算給定列表中的每個(gè)元素的平方值并放回一個(gè)新的列表

def pow2(x):

return x * x

L = [1, 2, 3, 4, 5, 6]

list1 = list(map(pow2, L))

print(list1)

輸出結(jié)果為:[1, 4, 9, 16, 25, 36]

上面已經(jīng)演示過(guò),pow2()可以直接使用匿名函數(shù):

L = [1, 2, 3, 4, 5, 6]

list1 = list(map(lambda x: pow(x, 2), L))

print(list1)

可見(jiàn)map函數(shù)作為高階函數(shù),事實(shí)上是把運(yùn)算規(guī)則抽象了,因此,我們不僅可以計(jì)算簡(jiǎn)單的f(x)=x*x,還可以計(jì)算任意復(fù)雜的函數(shù)。

實(shí)例2:計(jì)算兩個(gè)序列中對(duì)應(yīng)元素的和并保存至一個(gè)新的列表中

L = [1, 2, 3, 4, 5, 6]

T = (7, 8, 9, 10)

list1 = list(map(lambda x, y: x+y, L, T))

print(list1)

輸出結(jié)果為:[8, 10, 12, 14]

reduce函數(shù)

這里需要說(shuō)明一下:reduce函數(shù)在Python 2.x中跟map函數(shù)一樣都是Python內(nèi)置函數(shù),Python 3.x中已經(jīng)被轉(zhuǎn)移到functools模塊了。

reduce(function, sequence, initializer=None)

reduce函數(shù)的參數(shù)說(shuō)明:

接收一個(gè)函數(shù)參數(shù)、一個(gè)序列參數(shù)和一個(gè)可選的initalizer參數(shù)

如果可選參數(shù)initializer被提供,則相當(dāng)于把它作為sequence的一個(gè)元素插入sequence的首部

reduce函數(shù)的作用是:

把一個(gè)函數(shù)作用在指定的序列上,這個(gè)函數(shù)必須接收兩個(gè)參數(shù),然后把計(jì)算結(jié)果繼續(xù)和序列的下一個(gè)元素做累計(jì)計(jì)算,最終返回一個(gè)結(jié)果。簡(jiǎn)單來(lái)講,就是對(duì)一個(gè)序列中的元素做聚合運(yùn)算。

實(shí)例1:計(jì)算指定數(shù)列中所有元素的和

from functools import reduce

L = [1, 2, 3, 4, 5]

sum1 = reduce(lambda x, y: x + y, L)

print(sum1)

sum2 = reduce(lambda x, y: x + y, L, 6)

print(sum2)

輸出結(jié)果為:

15

21

這個(gè)過(guò)程相當(dāng)于:(((1 + 2) + 3) + 4) + 5

實(shí)例2:將數(shù)字字符串轉(zhuǎn)成int

from functools import reduce

def fn(x, y):

return int(x)*10 + int(y)

num = reduce(lambda x, y: int(x)*10 + y, '12345')

print(num)

也可以封裝成一個(gè)函數(shù):

from functools import reduce

def str2int(s):

return reduce(lambda x, y: int(x)*10 + int(y), s)

num = str2int('12345')

print(num)

也可以先通過(guò)map函數(shù)將字符串中的字符轉(zhuǎn)成int,然后再通過(guò)reduce進(jìn)行運(yùn)算:

from functools import reduce

def str2int(s):

def char2num(c):

return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[c]

return reduce(lambda x, y: x*10 + y, map(char2num, s))

num = str2int('12345')

print(num)

其實(shí)char2sum也可以用匿名函數(shù)來(lái)實(shí)現(xiàn),但是可讀性不太好。另外我舉這個(gè)例子的本義不是為了單純的演示map/reduce/匿名函數(shù)的使用,而是想說(shuō)明嵌套函數(shù)與高階函數(shù)綜合使用的場(chǎng)景,這在某些場(chǎng)景下可以使代碼邏輯變得更清晰。

filter函數(shù)

filter(function, iterable)

filter函數(shù)的參數(shù)說(shuō)明:

filter函數(shù)接收一個(gè)函數(shù)參數(shù)和一個(gè)可迭代對(duì)象參數(shù),��數(shù)參數(shù)可以為None

函數(shù)的返回值(True或False)用于判斷可迭代對(duì)象的當(dāng)前元素是否要保留

filter函數(shù)的作用是:

用于過(guò)濾可迭代對(duì)象,具體過(guò)程是:把傳入的函數(shù)依次作用于可迭代對(duì)象的每個(gè)元素,如果函數(shù)返回值為T(mén)ure則保留該元素,如果返回值為False則丟棄該元素,并最終把保留的元素作為一個(gè)iterator(迭代器)返回。如果function是None,則根據(jù)可迭代對(duì)象各元素的真值測(cè)試結(jié)果決定是否保留該元素。

與Python內(nèi)置的filter函數(shù)作用剛好相反的函數(shù)是itertools.filterfalse(function, sequence),它用于過(guò)濾出序列中通過(guò)function函數(shù)計(jì)算結(jié)果為False的元素。

實(shí)例1:分別打印出指定列表中的奇數(shù)和偶數(shù)

from itertools import filterfalse

L = [1, 2, 3, 4, 5, 6, 7, 8, 9]

odd_num = list(filter(lambda x: x % 2 == 1, L))

even_num = list(filterfalse(lambda x: x%2 == 1, L))

print('奇數(shù):', odd_num)

print('偶數(shù):', even_num)

輸出結(jié)果:

奇數(shù): [1, 3, 5, 7, 9]

偶數(shù): [2, 4, 6, 8]

實(shí)例2:刪除序列中的空字符串

L = ['ABC', '', 'DEF', ' ', '1233', None]

list1 = list(filter(None, L))

print(list1)

輸出結(jié)果為:['ABC', 'DEF', ' ', '1233']

由于第4個(gè)由3個(gè)空白字符組成的字符串的真值測(cè)試結(jié)果為T(mén)rue,因此它還是會(huì)被保留。被看來(lái)還是需要傳遞個(gè)函數(shù)參數(shù)才行:

L = ['ABC', '', 'DEF', ' ', '1233', None]

list1 = list(filter(lambda s: s and s.strip(), L))

print(list1)

輸出結(jié)果:['ABC', 'DEF', '1233']

sorted函數(shù)

sorted(iterable[, key][, reverse])

sorted函數(shù)的參數(shù)說(shuō)明:

sorted函數(shù)可以接收一個(gè)可迭代對(duì)象iterable作為必選參數(shù),還可以接收兩個(gè)可選參數(shù)key和reverse,但是這兩個(gè)可選參數(shù)如果要提供的話,需要作為關(guān)鍵字參數(shù)進(jìn)行傳遞;

參數(shù)key接收的是一個(gè)函數(shù)名,該函數(shù)用來(lái)實(shí)現(xiàn)自定義排序;如,要按照絕對(duì)值大小進(jìn)行排序:key=abs

參數(shù)reverse接收的是一個(gè)布爾值:如果reverse=Ture,表示倒敘排序,如果reverse=False,表示正序排序;reverse默認(rèn)值為False

關(guān)于參數(shù)key的進(jìn)一步說(shuō)明: 排序的核心是比較兩個(gè)元素的大小。如果要比較的是兩個(gè)數(shù)字,我們可以直接比較;如果是字符串,也可以按照ASCII碼的大小進(jìn)行比較。但是,如果要比較的元素是兩個(gè)序列或dict等復(fù)雜數(shù)據(jù)呢?這時(shí),我們可能需要指定一個(gè)計(jì)算“用于比較的值”的運(yùn)算規(guī)則,比如我們指定取兩個(gè)dict中的某個(gè)共同的key對(duì)應(yīng)的值來(lái)進(jìn)行比較,又比如我們指定用將兩個(gè)字符串都轉(zhuǎn)換為小寫(xiě)或者大寫(xiě)后的結(jié)果值進(jìn)行比較。其實(shí)說(shuō)簡(jiǎn)單點(diǎn),參數(shù)key這個(gè)函數(shù)作用是:計(jì)算/獲取用來(lái)進(jìn)行比較的值。如果我們需要自定義這個(gè)函數(shù)時(shí),需要注意該函數(shù)應(yīng)該有一個(gè)參數(shù),這個(gè)參數(shù)接收的就是可迭代對(duì)象中每個(gè)元素的值。

sorted函數(shù)的作用是:

對(duì)可迭代對(duì)象iterable中的元素進(jìn)行排序,并將排序結(jié)果作為一個(gè)新的list返回。

實(shí)例1:數(shù)字列表排序

list1 = sorted([10, 9, -21, 13, -30])

list2 = sorted([10, 9, -21, 13, -30], key=abs)

list3 = sorted([10, 9, -21, 13, -30], key=abs, reverse=True)

print(list1)

print(list2)

print(list3)

輸出結(jié)果:

[-30, -21, 9, 10, 13]

[9, 10, 13, -21, -30]

[-30, -21, 13, 10, 9]

實(shí)例2:字符串列表排序

list1 = sorted(['how', 'What', 'check', 'Zero'])

list2 = sorted(['how', 'What', 'check', 'Zero'], key=lower)

list3 = sorted(['how', 'What', 'check', 'Zero'], key=lower, reverse=True)

print(list1)

print(list2)

print(list3)

輸出結(jié)果:

['What', 'Zero', 'check', 'how']

['check', 'how', 'What', 'Zero']

['Zero', 'What', 'how', 'check']

實(shí)例3:tuple列表排序

假設(shè)我們用一組tuple表示姓名和年齡,然后用sorted()函數(shù)分別按姓名升序和年齡降序進(jìn)行排序:

def sort_by_name(t):

return t[0]

def sort_by_age(t):

return t[1]

L = [('Tom', 18), ('Jerry', 15), ('Peter', 16), ('John', 20)]

list1 = sorted(L, key=sort_by_name)

list2 = sorted(L, key=sort_by_age, reverse=True)

print('sort by name asc: ', list1)

print('sort by age desc: ', list2)

輸出結(jié)果:

sort by name asc: [('Jerry', 15), ('John', 20), ('Peter', 16), ('Tom', 18)]

sort by age desc: [('John', 20), ('Tom', 18), ('Peter', 16), ('Jerry', 15)]

實(shí)例4:字典內(nèi)容排序

對(duì)字典排序的方法有很多中,但核心思想都是一樣的:把dict中的key或value或item分離出來(lái)放到一個(gè)list中,然后在對(duì)這個(gè)list進(jìn)行排序,從而間接實(shí)現(xiàn)對(duì)dict的排序。

D = {'Tom': 18, 'Jerry': 15, 'Peter': 16, 'John': 20}

list1 = sorted(D.items(), key=lambda d: d[0])

list2 = sorted(D.items(), key=lambda d: d[1], reverse=True)

print('sort by key asc:', list1)

print('sort by value desc:', list2)

輸出結(jié)果:

sort by key asc: [('Jerry', 15), ('John', 20), ('Peter', 16), ('Tom', 18)]

sort by value desc: [('John', 20), ('Tom', 18), ('Peter', 16), ('Jerry', 15)]

五、內(nèi)置函數(shù)

Python解釋器有許多內(nèi)置的函數(shù)和類(lèi)型,有一些之前已經(jīng)用到過(guò),比如:

數(shù)學(xué)函數(shù):abs()、max()、min()、pow()、sum()

類(lèi)型轉(zhuǎn)換函數(shù):int()、float()、str()、bool()、list()、tuple()、dict()、set()

進(jìn)制轉(zhuǎn)換函數(shù):bin()、oct()、hex()

高階函數(shù):map()、filter()、sorted()

打開(kāi)文件用的函數(shù):的open()

輸入與輸出函數(shù):input()、raw_input()、print()

獲取對(duì)象內(nèi)存地址的函數(shù):id()

這些函數(shù)我們?cè)谥暗奈恼轮谢径佳菔玖?#xff0c;不在此贅述。關(guān)于他們的詳細(xì)說(shuō)明以及其它內(nèi)置函數(shù)的使用可以參考下面給出的列表及官方文檔連接地址。

Python 3相對(duì)于Python 2的內(nèi)置函數(shù)有些變動(dòng):

新增了一些內(nèi)置方法,如:ascii()、bytes()、exec()

刪除了一些內(nèi)置方法, 如:cmp()、execfile()

移動(dòng)了一些內(nèi)置方法,如:reduce()被移動(dòng)到了functools模塊下

修改了一些內(nèi)置方法,如:sorted()函數(shù)在Python 3.5的文檔中么有再提到cmp參數(shù)了(貌似用不到這個(gè)參數(shù))

Python 3中的高階函數(shù)還有一個(gè)比較大的改變,如map()和filter()在Python 2中是直接返回一個(gè)列表(list),而在Python 3中是返回一個(gè)迭代器(Iterator)。

Python 3.5內(nèi)置函數(shù)列表(官方文檔地址)

Python 2.7內(nèi)置函數(shù)列表(官方文檔地址)

六、總結(jié)

這里講了分別講了Python中函數(shù)的一些高級(jí)應(yīng)用,如果能把這些內(nèi)容整合起來(lái)靈活運(yùn)用會(huì)發(fā)揮很大的威力。比如后面要說(shuō)到的裝飾就是高階函數(shù)、嵌套函數(shù)以及閉包的一個(gè)典型應(yīng)用。

總結(jié)

以上是生活随笔為你收集整理的python进行linux编程,Python之函数进阶的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。