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

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

- 函數(shù)式

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

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

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

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

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

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

- 需要講述

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

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

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

? ? - 偏函數(shù) :

### lambda 表達(dá)式

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

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

? ? - 一個表達(dá)式,沒有方式名稱

```python

# 定義一個返回函數(shù),返回fun2。通過變量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

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

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

- 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 舉例

# 將一個列表中的元素乘以10,并得到新列表

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

print(l1)

l2 = []

for i in l1:

? ? l2.append(i * 10)

print(l2)

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

def mulTen(n):

? ? return n * 10

l3 = map(mulTen,l1)

print (l3)

```

?reduce

- 意愿是歸并,縮減

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

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

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

- reduce 需要 functools包

```python

from functools import reduce

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

def add(x,y):

? ? return x + y

# 對于列表【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ù)

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

- 跟map 相比:

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

? ? - 不同: map會生成一個跟原來數(shù)據(jù)相對應(yīng)的新隊列

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

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

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

? ? ? ? - 返回值一定是個布爾值

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

```python

# filter 函數(shù)

# 對一個列表,對其進(jìn)行過濾,偶數(shù)組成一個新列表

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

# 過濾函數(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)

#返回一個可迭代對象

print(res)

print([i for i in res])

```

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

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

- key: 在排序中對每一元素進(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]

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

# abs是求絕對值的意思

# 即按照絕對值的倒敘進(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é)一點的返回函數(shù)的例子

# args 參數(shù)列表

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

# myF5使用了外部變量,這個變量是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)一個函數(shù)在內(nèi)部定義函數(shù),并且內(nèi)部的函數(shù)應(yīng)用外部函數(shù)的參數(shù)或局部變量,當(dāng)內(nèi)部函數(shù)被作返回值的時候,相關(guān)參數(shù)和變量保存在返回的函數(shù)中,這種結(jié)果,叫做閉包。

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

```python

# 閉包常見的坑

def count():

? ? # 定義列表

? ? fs = []

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

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

? ? ? ? def f():

? ? ? ? ? ? return i*i

? ? ? ? fs.append(f)

? ? return fs

f1,f2,f3 = count()

print(f1())

print(f2())

print(f3())

```

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

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

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

- 解決方案:在創(chuàng)建一個函數(shù),用該函數(shù)的參數(shù)綁定循環(huán)變量的當(dāng)前值,無論該循環(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裝飾器就是用于拓展原來函數(shù)功能的一種函數(shù),這個函數(shù)的特殊之處在于它的返回值也是一個函數(shù)

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

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

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

```python

# 我們要想拓展原來函數(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í)行,新加入功能才會生效

```

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

- 實現(xiàn)一個最簡陋的裝飾器,不使用任何語法和高級語法,看看裝飾器最原始的面貌

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

- 所以這里裝飾器就像一個注入符號:拓展了原來函數(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

# 上面定義裝飾器,使用的時候需要用到@ ,此符號是python的語法糖

@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)

```

- 多個裝飾器

```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)于一個由特定參數(shù)的函數(shù)體

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

```python

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

int("12345")

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

int("12345",base=8)

```

```python

# 新建一個函數(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)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容