高階python 函數(shù)式編程

高階python 函數(shù)式編程

- 函數(shù)式

函數(shù)式編程(FunctionalProgramming)

- 基于lambda演示得一種編程方式

? ? - 程序中只有函數(shù)

? ? - 函數(shù)可以做為參數(shù)外莲,作為返回值,

? ? - 純函數(shù)式編程語(yǔ)言 : LISP,Haskell

- python函數(shù)式編程只是借鑒函數(shù)式編程得一些特點(diǎn)兔朦,可以理解成一半函數(shù)式一半python

- 需要講述

? ? - 高階函數(shù) :把函數(shù)作為參數(shù)使用得函數(shù)偷线,叫高階函數(shù);

? ? - 返回函數(shù) :把函數(shù)做為返回值得函數(shù)沽甥,叫返回函數(shù)声邦;

? ? - 裝飾器 :就是用于拓展原來(lái)函數(shù)功能的一種函數(shù),這個(gè)函數(shù)的特殊之處在于它的返回值也是一個(gè)函數(shù)摆舟,使用python裝飾器的好處就是在不用更改原函數(shù)的代碼前提下給函數(shù)增加新的功能亥曹;

? ? - 偏函數(shù) :

### lambda 表達(dá)式

- 函數(shù):最大程度復(fù)用代碼

- lambda表達(dá)式(匿名函數(shù))

? ? - 一個(gè)表達(dá)式邓了,沒(méi)有方式名稱

```python

# 定義一個(gè)返回函數(shù),返回fun2媳瞪。通過(guò)變量fun進(jìn)行接收返回值骗炉,打印返回值類型,并調(diào)用返回函數(shù)材失。

def fun(a):

? ? def fun2():

? ? ? ? print "this is fun2"

? ? print a

? ? return fun2

fun = fun(2)

print (type(fun))

print fun()

```

系統(tǒng)高階函數(shù) - map

- 原意就是映射痕鳍,即把集合或列表得元素硫豆,每一個(gè)元素都按照一定規(guī)則進(jìn)行操作龙巨,生成一個(gè)新的列表或者集合

- map函數(shù)是系統(tǒng)提供得具有映射功能得函數(shù),返回值是一個(gè)迭代對(duì)象

- map python2 傳入什么類型數(shù)據(jù)返回什么類型數(shù)據(jù)

- map python3 傳入什么類型數(shù)據(jù)返回 ..."map"... 類型數(shù)據(jù)

- map(...)

? ? map(function, sequence[, sequence, ...]) -> list


? ? Return a list of the results of applying the function to the items of

? ? the argument sequence(s).? If more than one sequence is given, the

? ? function is called with an argument list consisting of the corresponding

? ? item of each sequence, substituting None for missing values when not all

? ? sequences have the same length.? If the function is None, return a list of

? ? the items of the sequence (or a list of tuples if more than one sequence).

```python

# map 舉例

# 將一個(gè)列表中的元素乘以10熊响,并得到新列表

l1 = [i for i in range(10)]

print(l1)

l2 = []

for i in l1:

? ? l2.append(i * 10)

print(l2)

# map 實(shí)現(xiàn)以上功能

def mulTen(n):

? ? return n * 10

l3 = map(mulTen,l1)

print (l3)

```

?reduce

- 意愿是歸并旨别,縮減

- 把一個(gè)可迭代的對(duì)象最后歸并成一個(gè)結(jié)果

- 對(duì)于函數(shù)參數(shù)要求:必須有兩個(gè)參數(shù),必須有返回結(jié)果

- reduce[1,2,3,4,5] = fun(fun(fun(fun(1,2),3),4),5)

- reduce 需要 functools包

```python

from functools import reduce

# 定義個(gè)操作函數(shù)

def add(x,y):

? ? return x + y

# 對(duì)于列表【1汗茄,2秸弛,3,4洪碳,5递览,6】執(zhí)行add 操作

rst = reduce(add ,[1,2,3,4,5,6])

print (rst)

# 以上reduce可看作下面進(jìn)行運(yùn)算

rst2 =add(add(add(add(add(1,2),3),4),5),6)

print(rst2)

```

filter 函數(shù)

- 過(guò)濾函數(shù):對(duì)一組數(shù)據(jù)進(jìn)行過(guò)濾,符合條件的數(shù)據(jù)會(huì)生成一個(gè)新的列表并返回

- 跟map 相比:

? ? - 相同: 都對(duì)列表的每一個(gè)元素逐一進(jìn)行操作

? ? - 不同: map會(huì)生成一個(gè)跟原來(lái)數(shù)據(jù)相對(duì)應(yīng)的新隊(duì)列

? ? ? ? ? filter 不一定瞳腌,只要符合條件的才會(huì)進(jìn)入新的數(shù)據(jù)集合

? ? - filter函數(shù)怎么寫(xiě):

? ? ? ? - 利用給定函數(shù)進(jìn)行判斷

? ? ? ? - 返回值一定是個(gè)布爾值

? ? ? ? - 調(diào)用格式:filter(f,data),f是過(guò)濾函數(shù)绞铃,data是數(shù)據(jù)

```python

# filter 函數(shù)

# 對(duì)一個(gè)列表,對(duì)其進(jìn)行過(guò)濾嫂侍,偶數(shù)組成一個(gè)新列表

# 需要定義過(guò)濾函數(shù)

# 過(guò)濾函數(shù)要求有輸入儿捧,返回布爾值

def isEven(a):

? ? return a % 2 == 0

l = [1,2,3,4,54,3,2,32,32,32,3,333,44,32,4325]

res = filter(isEven,l)

#返回一個(gè)可迭代對(duì)象

print(res)

print([i for i in res])

```

?高階函數(shù)-排序

- 把一個(gè)序列按照給定的算法進(jìn)行排序

- key: 在排序中對(duì)每一元素進(jìn)行key函數(shù)運(yùn)算,可以理解成按照key函數(shù)定義的邏輯進(jìn)行排序

- python2 和 python3 相差巨大

```python

#排序案例1

a = [12,32,43,543,56,654,6576,5765,765,645,6546645,654645]

al = sorted(a)

ad = sorted(a,reverse=True)

print(al)

print(ad)

```

```python

#排序案例2

a = [-12,2,32,-455,321,32]

# 按照絕對(duì)值進(jìn)行排序

# abs是求絕對(duì)值的意思

# 即按照絕對(duì)值的倒敘進(jìn)行排序

al = sorted(a, key=abs, reverse=True)

print(al)

```

```python

#sorted 排序案例

astr = ['dana','whj','jin','WTt','Zs','sz']

str1 = sorted(astr)

print(str1)

str2 = sorted(astr,key=str.lower)

print(str2)

```

?高階函數(shù)-返回函數(shù)

```python

# 負(fù)責(zé)一點(diǎn)的返回函數(shù)的例子

# args 參數(shù)列表

# myF4 定義函數(shù)挑宠,返回內(nèi)部定義的函數(shù)myF5

# myF5使用了外部變量菲盾,這個(gè)變量是myF4的參數(shù)

def myF4( *args):

? ? def myF5():

? ? ? ? rst = 0

? ? ? ? for n in args:

? ? ? ? ? ? rst += n

? ? ? ? return rst

? ? return myF5

f5 = myF4(1,2,3,4,5,6,7,8,9,10)

f5()

```

```python

f6 = myF4(10,20,30)

f6()

```

閉包(closure)

- 當(dāng)一個(gè)函數(shù)在內(nèi)部定義函數(shù),并且內(nèi)部的函數(shù)應(yīng)用外部函數(shù)的參數(shù)或局部變量各淀,當(dāng)內(nèi)部函數(shù)被作返回值的時(shí)候懒鉴,相關(guān)參數(shù)和變量保存在返回的函數(shù)中,這種結(jié)果碎浇,叫做閉包疗我。

- 上面定義的myF4 是一個(gè)標(biāo)準(zhǔn)的閉包結(jié)構(gòu)

```python

# 閉包常見(jiàn)的坑

def count():

? ? # 定義列表

? ? fs = []

? ? for i in range(1,4):

? ? ? ? # 定義了一個(gè)函數(shù)f

? ? ? ? def f():

? ? ? ? ? ? return i*i

? ? ? ? fs.append(f)

? ? return fs

f1,f2,f3 = count()

print(f1())

print(f2())

print(f3())

```

### 出現(xiàn)問(wèn)題:

- 造成上述情況的原因是,返回函數(shù)引用了變量i,i并非立即執(zhí)行南捂,而是等到三個(gè)函數(shù)都返回的時(shí)候才統(tǒng)一執(zhí)行吴裤,此時(shí)i已經(jīng)變成了3,最終調(diào)用的時(shí)候溺健,都返回的3*3

- 此問(wèn)題描述成:返回閉包時(shí)麦牺,返回函數(shù)不能引用任何循環(huán)變量

- 解決方案:在創(chuàng)建一個(gè)函數(shù)钮蛛,用該函數(shù)的參數(shù)綁定循環(huán)變量的當(dāng)前值,無(wú)論該循環(huán)變量以后如何改變剖膳,已經(jīng)綁定的函數(shù)參數(shù)值不在改變

```python

# 修改上述函數(shù)

def count1():

? ? def f(j):

? ? ? ? def g():

? ? ? ? ? ? return j*j

? ? ? ? return g

? ? fs = []

? ? for i in range(1,4):

? ? ? ? fs.append(f(i))

? ? return fs

f1,f2,f3 = count1()

print(f1())

print(f2())

print(f3)

```

裝飾器(Dercrator)

- python裝飾器就是用于拓展原來(lái)函數(shù)功能的一種函數(shù)魏颓,這個(gè)函數(shù)的特殊之處在于它的返回值也是一個(gè)函數(shù)

- 在不改動(dòng)函數(shù)代碼的基礎(chǔ)上無(wú)限制擴(kuò)展函數(shù)功能的一種機(jī)制,本質(zhì)上講吱晒,裝飾器是一個(gè)返回函數(shù)的高階函數(shù)

- 裝飾器使用:使用@語(yǔ)法甸饱,即在每次要擴(kuò)展到函數(shù)定義前面使用@+函數(shù)名

- 裝飾器先執(zhí)行裝飾器內(nèi)函數(shù),在執(zhí)行被裝飾函數(shù)仑濒。

```python

# 我們要想拓展原來(lái)函數(shù)代碼叹话,最直接的辦法就是侵入代碼里面修改,例如:

import time

def hello():

? ? startTime = time.time()

? ? print("hello")

? ? time.sleep(1)

? ? print("world")

? ? endTime = time.time()

? ? msecs = (endTime - startTime)*1000

? ? print("time is %d ms" %msecs)

hello()

```

- 避免直接侵入原函數(shù)修改墩瞳,但是生效需要再次執(zhí)行函數(shù)

```python

import time

def deco(func):

? ? startTime = time.time()

? ? func()

? ? endTime = time.time()

? ? msecs = (endTime - startTime)*1000

? ? print("time is %d ms" %msecs)

def func():

? ? print("hello")

? ? time.sleep(1)

? ? print("world")

f = func

deco(f)#只有把func()或者f()作為參數(shù)執(zhí)行驼壶,新加入功能才會(huì)生效

```

- 核心代碼區(qū)域有一千萬(wàn)個(gè)func()函數(shù),從func01()到func1kw(),按以上實(shí)現(xiàn)方案喉酌,想要拓展這一千萬(wàn)個(gè)函數(shù)功能热凹,就是要執(zhí)行一千萬(wàn)次deco()函數(shù)。這種方式不可取泪电。

- 實(shí)現(xiàn)一個(gè)最簡(jiǎn)陋的裝飾器般妙,不使用任何語(yǔ)法和高級(jí)語(yǔ)法,看看裝飾器最原始的面貌

- 這里的deco函數(shù)就是最原始的裝飾器相速,它的參數(shù)是一個(gè)函數(shù)碟渺,然后返回值也是一個(gè)函數(shù)。其中作為參數(shù)的這個(gè)函數(shù)func()就在返回函數(shù)wrapper()的內(nèi)部執(zhí)行和蚪。然后在函數(shù)func()前面加上@deco止状,func()函數(shù)就相當(dāng)于被注入了計(jì)時(shí)功能,現(xiàn)在只要調(diào)用func()攒霹,它就已經(jīng)變身為“新的功能更多”的函數(shù)了怯疤。

- 所以這里裝飾器就像一個(gè)注入符號(hào):拓展了原來(lái)函數(shù)的功能既不需要侵入函數(shù)內(nèi)更改代碼,也不需要重復(fù)執(zhí)行原函數(shù)催束。

```python

#既不需要侵入集峦,也不需要函數(shù)重復(fù)執(zhí)行

import time

def deco(func):

? ? def wrapper():

? ? ? ? startTime = time.time()

? ? ? ? func()

? ? ? ? endTime = time.time()

? ? ? ? msecs = (endTime - startTime)*1000

? ? ? ? print("time is %d ms" %msecs)

? ? return wrapper

# 上面定義裝飾器,使用的時(shí)候需要用到@ 抠刺,此符號(hào)是python的語(yǔ)法糖

@deco

def func():

? ? print("hello")

? ? time.sleep(1)

? ? print("world")

f = func #這里f被賦值為func塔淤,執(zhí)行f()就是執(zhí)行func()

f()

```

- 帶有參數(shù)的裝飾器

```python

import time

def deco(func):

? ? def wrapper(a,b):

? ? ? ? startTime = time.time()

? ? ? ? func(a,b)

? ? ? ? endTime = time.time()

? ? ? ? msecs = (endTime - startTime)*1000

? ? ? ? print("time is %d ms" %msecs)

? ? return wrapper

@deco

def func(a,b):

? ? print("hello,here is a func for add :")

? ? time.sleep(1)

? ? print("result is %d" %(a+b))

f = func

f(3,4)

```

- 帶有不定參數(shù)的裝飾器

```python

import time

def deco(func):

? ? def wrapper(*args, **kwargs):

? ? ? ? startTime = time.time()

? ? ? ? func(*args, **kwargs)

? ? ? ? endTime = time.time()

? ? ? ? msecs = (endTime - startTime)*1000

? ? ? ? print("time is %d ms" %msecs)

? ? return wrapper

@deco

def func(a,b):

? ? print("hello速妖,here is a func for add :")

? ? time.sleep(1)

? ? print("result is %d" %(a+b))

@deco

def func2(a,b,c):

? ? print("hello高蜂,here is a func for add :")

? ? time.sleep(1)

? ? print("result is %d" %(a+b+c))

f = func

func2(3,4,5)

f(3,4)

```

- 多個(gè)裝飾器

```python

import time

def deco01(func):

? ? def wrapper(*args, **kwargs):

? ? ? ? print("this is deco01")

? ? ? ? startTime = time.time()

? ? ? ? func(*args, **kwargs)

? ? ? ? endTime = time.time()

? ? ? ? msecs = (endTime - startTime)*1000

? ? ? ? print("time is %d ms" %msecs)

? ? ? ? print("deco01 end here")

? ? return wrapper

def deco02(func):

? ? def wrapper(*args, **kwargs):

? ? ? ? print("this is deco02")

? ? ? ? func(*args, **kwargs)

? ? ? ? print("deco02 end here")

? ? return wrapper

@deco01

@deco02

def func(a,b):

? ? print("hello,here is a func for add :")

? ? time.sleep(1)

? ? print("result is %d" %(a+b))

f = func

f(3,4)

```

?偏函數(shù)(Partial)

- 參數(shù)固定的函數(shù)罕容,相當(dāng)于一個(gè)由特定參數(shù)的函數(shù)體

- functools.partial的作用是:把一個(gè)函數(shù)某些函數(shù)固定备恤,返回一個(gè)新函數(shù)

```python

# 把字符串轉(zhuǎn)換十進(jìn)制數(shù)字

int("12345")

# 求八進(jìn)制的字符串12345稿饰,表示成十進(jìn)制的數(shù)字是多少

int("12345",base=8)

```

```python

# 新建一個(gè)函數(shù),此函數(shù)是默認(rèn)輸入的字符串是16進(jìn)制數(shù)字

# 把此字符串返回十進(jìn)制的數(shù)字

def int16(x,base=16):

? ? return int(x,base)

int16("12345")

```

```python

import functools

int16 = functools.partial(int,base=16)

int16("12345")

```

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末露泊,一起剝皮案震驚了整個(gè)濱河市喉镰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌惭笑,老刑警劉巖侣姆,帶你破解...
    沈念sama閱讀 222,378評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異沉噩,居然都是意外死亡捺宗,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門屁擅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)偿凭,“玉大人产弹,你說(shuō)我怎么就攤上這事派歌。” “怎么了痰哨?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,983評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵胶果,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我斤斧,道長(zhǎng)早抠,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,938評(píng)論 1 299
  • 正文 為了忘掉前任撬讽,我火速辦了婚禮蕊连,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘游昼。我一直安慰自己甘苍,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,955評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布烘豌。 她就那樣靜靜地躺著载庭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪廊佩。 梳的紋絲不亂的頭發(fā)上囚聚,一...
    開(kāi)封第一講書(shū)人閱讀 52,549評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音标锄,去河邊找鬼顽铸。 笑死,一個(gè)胖子當(dāng)著我的面吹牛料皇,可吹牛的內(nèi)容都是我干的谓松。 我是一名探鬼主播簸淀,決...
    沈念sama閱讀 41,063評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼毒返!你這毒婦竟也來(lái)了租幕?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,991評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤拧簸,失蹤者是張志新(化名)和其女友劉穎劲绪,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體盆赤,經(jīng)...
    沈念sama閱讀 46,522評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡贾富,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,604評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了牺六。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片颤枪。...
    茶點(diǎn)故事閱讀 40,742評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖淑际,靈堂內(nèi)的尸體忽然破棺而出畏纲,到底是詐尸還是另有隱情,我是刑警寧澤春缕,帶...
    沈念sama閱讀 36,413評(píng)論 5 351
  • 正文 年R本政府宣布盗胀,位于F島的核電站,受9級(jí)特大地震影響锄贼,放射性物質(zhì)發(fā)生泄漏票灰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,094評(píng)論 3 335
  • 文/蒙蒙 一宅荤、第九天 我趴在偏房一處隱蔽的房頂上張望屑迂。 院中可真熱鬧,春花似錦冯键、人聲如沸惹盼。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,572評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)逻锐。三九已至,卻和暖如春雕薪,著一層夾襖步出監(jiān)牢的瞬間昧诱,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,671評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工所袁, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留盏档,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,159評(píng)論 3 378
  • 正文 我出身青樓燥爷,卻偏偏與公主長(zhǎng)得像蜈亩,于是被迫代替她去往敵國(guó)和親懦窘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,747評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容