python語法隨意重斑,對(duì)于習(xí)慣了java和c這樣語法規(guī)范的語言來說,python用起來多多少少還有一些不習(xí)慣,最近在學(xué)習(xí)過程中見到了一些python中奇怪的函數(shù)類型构韵,而僅僅通過這些函數(shù)類型的名字也看不透這些函數(shù)到底是什么樣子的航邢,自己了解過后寫了下來耕赘。
我見到的奇怪的函數(shù)類型有四種,分別是:匿名函數(shù)膳殷、裝飾器函數(shù)操骡、生成器函數(shù)以及高階函數(shù)。
匿名函數(shù)
匿名函數(shù)在java中我們可能會(huì)想到匿名內(nèi)部類赚窃,或者是java中的lambda表達(dá)式册招,而實(shí)際上python中的匿名函數(shù)也是通過lambda來實(shí)現(xiàn)的,不過注意的是勒极,python中真的是通過lambda這個(gè)關(guān)鍵字來實(shí)現(xiàn)是掰。
例如:
add = lambda x, y: x + y
result = add(3, 5) # 結(jié)果為8
與普通函數(shù)不同,它們是一種更加簡潔的方式來編寫小型臨時(shí)函數(shù)。有了這個(gè)例子相信大家一下就能明白python中的匿名函數(shù)了辱匿。
裝飾器函數(shù)
裝飾器函數(shù)更多的是直接叫裝飾器键痛,裝飾器僅看名字可能會(huì)想到是起一個(gè)裝飾的功能,但是怎么樣去裝飾呢匾七?還是直接看例子
import time
def func():
????for x in range(1,1000000):
????????print(x)
def decoration(function):
????startTime = time.time()
????function()
????print(time.time()-startTime)
if __name__ == '__main__': ???? ????decoration(func)????#3.1974148750305176
假如我們想要測(cè)試一個(gè)函數(shù)的運(yùn)行時(shí)間絮短,我們一般的做法就是在函數(shù)的上下文上添加計(jì)時(shí)器,但是在python中昨忆,函數(shù)是可以作為一個(gè)參數(shù)傳入函數(shù)中的丁频,所以我們只需要將模板寫好,將所需要測(cè)試的函數(shù)傳進(jìn)裝飾器中即可,裝飾器不僅可以裝飾函數(shù)席里,也可以裝飾類叔磷,所以這就是裝飾器的思想,所謂裝飾,其實(shí)就是將其他的函數(shù)或類作為參數(shù)傳入,在原有基礎(chǔ)上添加一些新邏輯或者屬性后,將這個(gè)新的函數(shù)或類返回的過程奖磁。
生成器函數(shù)
生成器函數(shù)就比較特殊了改基,生成器函數(shù)主要依賴yield關(guān)鍵字實(shí)現(xiàn),先上例子
def my_generator():
????yield 1
????yield 2
????yield 3
if __name__ == '__main__':
????g = my_generator()? # 創(chuàng)建生成器對(duì)象
????print(next(g))? # 1
????print(next(g))? # 2
????print(next(g))? # 3
#在 Python3.x 中咖为,可以使用 __next__() 方法來替代 next() 方法寥裂。
def my_generator():
????yield 1
????yield 2
????yield 3
????g = my_generator()
????print(g.__next__()) #1
????print(g.__next__()) #2
????print(g.__next__()) #3
#我們還可以使用 for 循環(huán)來進(jìn)行遍歷:
def my_generator():
????yield 1
????yield 2
????yield 3
for i in my_generator():
????print(i)
我們?cè)趈ava中使用函數(shù)返回值的時(shí)候使用的都是return,而且一個(gè)函數(shù)只能返回一個(gè)值或?qū)ο蟀钙#@已經(jīng)成為了我們的共識(shí)封恰,但是在python中可以通過yield關(guān)鍵字實(shí)現(xiàn)生成器函數(shù),一個(gè)yield關(guān)鍵字就是一個(gè)返回值褐啡,而且最重要的是诺舔,生成器被使用之后會(huì)創(chuàng)建一個(gè)生成器對(duì)象,我們可以使用next()函數(shù)遍歷生成器函數(shù)中的每一個(gè)返回值备畦,yield關(guān)鍵字就相當(dāng)于生成器函數(shù)中的斷點(diǎn)低飒,我們執(zhí)行一次next,就向下走一步懂盐,這個(gè)操作和java中的迭代器是一樣的褥赊,但是不一樣的是這個(gè)生成器對(duì)象可以直接用循環(huán)遍歷。但是最后為什么要叫生成器呢莉恼?這是因?yàn)榧偃鐚⑺械臄?shù)據(jù)都創(chuàng)建出來然后放入生成器中可能會(huì)非常占用空間拌喉,在創(chuàng)建生成器的時(shí)候也會(huì)花很多時(shí)間,而生成器并沒有將所需要返回的數(shù)據(jù)一下生成出來俐银,而只是利用算法尿背,在該返回的時(shí)候通過算法得到要返回的數(shù)據(jù),然后將這個(gè)數(shù)據(jù)聲明出來返回捶惜,這樣做既節(jié)省了時(shí)間又節(jié)省了空間田藐。
import time
if __name__ == '__main__':
????start_time = time.time()
????b = [x for x in range(100000000)]? # 創(chuàng)建列表
????print(time.time() - start_time)????# 4.012589454650879s
????start_time = time.time()
????a = (x for x in range(1000000))? # 創(chuàng)建生成器
????print(time.time() - start_time)????# 0.0s
創(chuàng)建一億個(gè)簡單的數(shù)字?jǐn)?shù)據(jù),list要花費(fèi)3-4s的時(shí)間吱七,但是生成器卻僅僅花費(fèi)了不到0.01s的時(shí)間汽久,這是生成器最與眾不同的地方。
高階函數(shù)
高階函數(shù)其實(shí)很簡單踊餐,只不過起了一個(gè)很高大上的名字景醇,其實(shí)前面的裝飾器就是一個(gè)高階函數(shù),因?yàn)樵趐ython中函數(shù)可以作為一個(gè)函數(shù)去傳入函數(shù)市袖,所以自然啡直,你可以先將一個(gè)函數(shù)傳進(jìn)來,然后再對(duì)傳進(jìn)來的函數(shù)做一些操作苍碟。例如下面的例子
def func(x,y):
????return x+y
def highOrder_function(function,x,y):
????return function(x,y)
if __name__ == '__main__':
????x = highOrder_function(func,10,5)
????print(x) #15
這就是一個(gè)高階函數(shù)酒觅,這個(gè)函數(shù)顯然沒有什么用處,但是通過這種思想可以做很多事情微峰,高階函數(shù)的存在主要原因還是依賴的函數(shù)可以作為變量去傳遞舷丹。
以上就是一些奇怪的函數(shù)類型,至少在java和c中很奇怪蜓肆,以上內(nèi)容僅個(gè)人觀點(diǎn)和理解颜凯,如果出錯(cuò)歡迎指正。