国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

[原創]Python入門學習之函數式編程

2019-11-14 17:02:52
字體:
來源:轉載
供稿:網友

一 前言

  初次接觸函數式編程是在學習分布式計算的時候,那時候對map/reduce是不明覺厲,也沒有懂多少原理方面的東西。Python中的函數式編程也算是初步了解一下map/reduce。所謂函數式編程,本質上是可以歸結為面向過程的程序設計,但是它的思想很接近數學計算。它比一般的編程范式要更抽象,而且純粹的函數式編程語言編寫的函數是沒有變量的,只要確定了輸入,那也就確定了輸出。它的另外一個特點就是把函數本身作為參數傳入到另一個函數中,允許返回一個函數。

 

二 高階函數(High-order Function)

  在Python中,函數名本質上也是一個變量。我們可以將一個函數名賦值給一個變量,再通過這個變量來調用函數。在使用python面向過程的程序設計中,一個帶有變量的函數是很普遍的設計,但是如果這個變量是一個函數,那么這個帶有變量的函數我們就稱之為高階函數了。

  一個簡單的高階函數示例:

def fun(n):    return n+1def highorder(x, y, f):    return f(x)+f(y)

 上面定義的highorder就是一個高階函數,它是可以在參數中接收其他函數的函數。

 

三 Map/Reduce

  有了上面的高階函數基礎,現在再來理解Map/Reduce就很容易了。Map函數接收兩個參數,一個是函數,另一個是Iterable。Map將函數依次作用在Iterable的每一個元素上,并把結果作為新的Iterator返回。

  看下面的示例:

def fun(n):    return n*2m=map(fun, [1,2,3,4,5])PRint(m)E:/Study/python>python hello_python.py[2, 4, 6, 8, 10]

   map把函數fun依次作用在列表的每一個元素上,就得到了[2,4,6,8,10]。

  如果嫌定義一個fun函數比較麻煩,可以使用lambda來進行簡化,如下:

m=map(lambda n:n*2, [1,2,3,4,5])

   再看Reduce的用法。Reduce同Map一樣,也是將一個函數依次作用在一個序列上,但是要求這個函數必須接收兩個函數。Reduce再把函數作用在前兩個參數的結果與下一個序列的元素上。

  下面就用Reduce來實現一個序列求和運算,見下例:

def add(x,y):    return x+yr=reduce(add, [1,2,3,4,5])print(r)E:/Study/python>python hello_python.py15

   它的lambda版本為:

r=reduce(lambda x,y:x+y, [1,2,3,4,5])

 

四 返回函數

  在前面就已經表述過函數是可以被賦值給一個變量的,那么既然函數可以返回一個變量,當然也是可以返回一個函數的。別看返回變量和返回函數本質上區別不大,但是這種返回函數的機制卻在應用中有著極大的作用。

  來看下面的示例:

def wrapper(*param):    def calc():        sum=0        for x in param:            sum=sum+x        return sum                return calc;f=wrapper(1,2,3,4,5)print(f())E:/Study/python>python hello_python.py15

   定義一個包裹函數wrapper,接收不定數量個參數。在調用此函數后,其會返回一個內部定義的函數,這個函數要在真正調用它時才會執行。另外還要注意的是,calc函數中訪問的數據是由wrapper帶進來的,并且這些參數會與calc被保存在一起,我們稱之為“閉包”(closure)。

 

五 閉包(Closure)

  初次接觸閉包,對其并不是十分的理解。仍以四中的代碼作為示例。

  wrapper是一個函數,包括不定個數的參數param。比較特殊的地方是這個函數體中還定義了一個新的函數calc,這個新函數的函數體內正引用了一個外部函數wrapper的參數,也就是說,外部函數傳遞過來的參數已經和calc函數綁定到了一起,形成了一個新函數。我們可以把param看成是這個新函數的一個配置信息。配置信息如果不一樣,那函數的輸出當然也就不一樣了。

  為了更好的理解閉包,看以下代碼示例:

def wrapper(conf):    def calc(n):        return conf+n    return calcf1=wrapper(1)f2=wrapper(2)print(f1(100))print(f2(100))E:/Study/python>python hello_python.py101102

   分析上述代碼,調用wrapper(1)時會返回一個函數,并且這個函數的配置信息是conf的值為1。再調用wrapper(2)時會返回另外一個函數,并且這個函數的配置信息是conf的值為2。所以在隨后的我們都傳入100參數來調用f1和f2時得到的結果為101和102,其根本原因就在于兩個函數的配置信息不一樣。

  值得我們注意的是,并不是外部函數的所有信息都會被內部函數做為配置信息,只有外部函數的參數才會被內部函數作為配置信息。至于外部函數的局部變量,就不會被做為配置信息了。

    

六 裝飾器(Decorator)

  發明Decorator的初衷是為了解決在不修改原有函數代碼的情況下,在函數調用前后增加其他功能,比如打印日志等。Decorator本質上就是一個返回函數的高階函數,看下面這個打印日志的decorator,代碼如下:

def decorator(func):    def wrapper():        print("Before invoked:")        func()        print("After invoked:")    return wrapper        def func():    print("Func invoked:")  f=decorator(func)f()E:/Study/python>python hello_python.pyBefore invoked:Func invoked:After invoked:

   上述代碼給func定義了一個裝飾器,在調用這個裝飾器時返回一個函數,在這個函數中加上需要的代碼后再調用func。但這里有一個問題,那就是原來可以直接調用func,現如今卻要調用f了。要解決這個問題很容易,因為在python中函數是可以賦值給一個變量的,只需要將f改成func就可以了。如下所示:

func=decorator(func)func()

   python中為實現這個機制提供了一個語法:@。在func前加上@decorator即可,相當于執行了func=decorator(func),這樣就解決了使用相同的名字來調用增加功能后的代碼。如下所示:

def decorator(func):    def wrapper():        print("Before invoked:")        func()        print("After invoked:")    return wrapper        @decoratordef func():    print("Func invoked:")  func()

   另外還有如何給decorator增加參數以及如何修改wrapper的__name__屬性為func的內容,這里就不講述了。

 

七 偏函數(Partial Function)

  何謂偏函數?偏函數就是給函數增加默認參數后的函數。在python中,可以使用functools.partial來生成一個函數的偏函數。拿python中的int()做示例,int()函數默認是按十進制轉換,如果想生成一個按8進制轉換的偏函數,可以如下實現:

print(int('12345'))int8=functools.partial(int, base=8)print(int8('12345'))

 

八 總結

  在這篇文章中,主要講述了函數式編程中的幾個基本概念。個人感覺最難理解的就是Decorator了,特別是其中的所謂配置信息。如有錯誤之處,敬請留言!!!


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 霍城县| 宝应县| 南昌市| 余江县| 莱芜市| 家居| 房山区| 紫阳县| 革吉县| 寿宁县| 宝丰县| 庆城县| 维西| 建平县| 蒙山县| 日土县| 绵阳市| 鄄城县| 左云县| 武邑县| 贡山| 吉林省| 彩票| 桂东县| 喀喇沁旗| 顺平县| 库尔勒市| 临武县| 横山县| 盐池县| 浙江省| 拜泉县| 邓州市| 滕州市| 修水县| 沽源县| 无为县| 句容市| 宜昌市| 芒康县| 石景山区|