亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Python的幾個高級語法概念淺析(lambda表達式閉包裝飾器)

 更新時間:2016年05月28日 12:44:44   投稿:mdxy-dxy  
本文主要記錄自己對幾個高級語法概念的理解:匿名函數(shù)、lambda表達式、閉包、裝飾器。這幾個概念并非Python特有,但本文只限于用Python做說明

1. 匿名函數(shù)
匿名函數(shù)(anonymous function)是指未與任何標識符綁定的函數(shù),多用在functional programming languages領域,典型應用場合:
1) 作為參數(shù)傳給高階函數(shù)(higher-order function ),如python中的built-in函數(shù)filter/map/reduce都是典型的高階函數(shù)
2) 作為高階函數(shù)的返回值(雖然此處的"值"實際上是個函數(shù)對象)
與命名函數(shù)(named function)相比,若函數(shù)只被調(diào)用1次或有限次,則匿名函數(shù)在語法上更輕量級。
具體語法上,python通過lambda語法支持函數(shù)體為表達式的匿名函數(shù),即:python的lambda表達式本質(zhì)上是個匿名函數(shù),但其函數(shù)體只能是個表達式,不能包含其它語句。
此外,高級動態(tài)語言常借助匿名函數(shù)實現(xiàn)閉包(closure)或裝飾器(decorator)等高級語法。
在一些場合下,lambda表達式的使用使得python程序看起來非常簡潔。例如,下面是根據(jù)value對dict元素做排序的代碼示例:

>>> foo = {'father' : 65, 'mother' : 62, 'sister' : 38, 'brother' : 29, 'me' : 28}
>>> sorted(foo.iteritems(), key=lambda x: x[1])
[('me', 28), ('brother', 29), ('sister', 38), ('mother', 62), ('father', 65)]

2. 閉包
閉包(closure)本質(zhì)上是一個包含了其引用環(huán)境(referencing environment)的函數(shù)或函數(shù)引用,這里的"引用環(huán)境"通常由一張表來維護,該表存儲了函數(shù)體會訪問的非局部變量(non-local variables)的引用。
與C語言中的函數(shù)指針相比,閉包允許嵌套函數(shù)訪問其作用域外的non-local變量,這與Python解釋器對變量的作用域查找規(guī)則有關(Python支持LEGB的查找規(guī)則,想深究的話,可以參考<Learning Python>第4版第17章Scopes關于作用域及查找規(guī)則的詳細講解,或者查看這篇文章 做快速了解)。
對于運行時內(nèi)存分配模型會在線性棧上創(chuàng)建局部變量的語言來說(典型如C語言),通常很難支持閉包。因為這些語言底層實現(xiàn)中,若函數(shù)返回,則函數(shù)中定義的局部變量均會隨著函數(shù)棧被回收而銷毀。但閉包在底層實現(xiàn)上要求其要訪問的non-local變量在閉包被執(zhí)行的時候保持有效,直到這個閉包的生命周期結(jié)束,這意外著這些non-local變量只有在其確定不再被使用時才能銷毀,而不能隨著定義這些變量的函數(shù)返回銷毀。因此,天生支持閉包的語言通常采用garbage collection的方式管理內(nèi)存,因為gc機制保證了變量只有不再被引用時才會由系統(tǒng)銷毀并回收其內(nèi)存空間。
具體語法上,閉包通常伴隨著函數(shù)嵌套定義。以Python為例,一個簡單的閉包示例如下:

#!/bin/env python
#-*- encoding: utf-8 -*-

def startAt_v1(x):
 def incrementBy(y):
  return x + y 
 print 'id(incrementBy)=%s' % (id(incrementBy))
 return incrementBy

def startAt_v2(x):
 return lambda y: x + y 

if '__main__' == __name__:
 c1 = startAt_v1(2)
 print 'type(c1)=%s, c1(3)=%s' % (type(c1), c1(3))
 print 'id(c1)=%s' % (id(c1))
 
 c2 = startAt_v2(2)
 print 'type(c2)=%s, c2(3)=%s' % (type(c2), c2(3))

執(zhí)行結(jié)果如下:

id(incrementBy)=139730510519782
type(c1)=<type 'function'>, c1(3)=5
id(c1)=139730510519782
type(c2)=<type 'function'>, c2(3)=5

上述示例中,startAt_v1和startAt_v2均實現(xiàn)了閉包,其中:v1借助嵌套定義函數(shù)實現(xiàn);v2則借助lambda表達式/匿名函數(shù)來實現(xiàn)。
我們以v1為例對閉包做說明:
1) 函數(shù)startAt_v1接受1個參數(shù),返回1個函數(shù)對象,而這個函數(shù)對象的行為由嵌套定義的函數(shù)incrementBy實現(xiàn)。
2) 對函數(shù)incrementBy來說,變量x就是所謂的non-local變量(因為x既非該函數(shù)定義的局部變量,又非普通意義上的全局變量),incrementBy實現(xiàn)具體的函數(shù)行為并返回。
3) main入口的c1接收到的返回值是個函數(shù)對象,從id(incrementBy) == id(c1)可斷定,c1"指向"的對象與函數(shù)名incrementBy"指向"的其實是同一個函數(shù)對象。
4) 受益于Python對閉包的支持,與普通函數(shù)的對象相比,c1指向的對象可以訪問不在其函數(shù)作用域內(nèi)的non-local變量,而這個變量是由incrementBy的外層包裝函數(shù)startAt_v1的入?yún)⑻峁┑?,于是,相當于c1指向的函數(shù)對象對其外層包裝函數(shù)的入?yún)⒕哂?記憶"功能,通過調(diào)用外層包裝函數(shù)創(chuàng)建閉包時,不同的入?yún)⒈粌?nèi)層函數(shù)作為引用環(huán)境維護起來。
5) 調(diào)用c1(3)時,傳入的參數(shù)與引用環(huán)境維護的外層包裝函數(shù)的參數(shù)一起運算得到最終結(jié)果。
以上步驟分析說明了一個閉包從創(chuàng)建到執(zhí)行的基本原理,理解這個case后,閉包的概念也應該清晰了。

3. 裝飾器
python支持裝飾器(decorator)語法。裝飾器的概念對于初學者來說比較晦澀,因為它涉及到函數(shù)式編程的幾個概念(如匿名函數(shù)、閉包),這也是本文先介紹匿名函數(shù)和閉包的原因。

我們引用這篇文章對裝飾器的定義:
A decorator is a function that takes a function object as an argument, and returns a function object as a return value.
從這個定義可知,裝飾器本質(zhì)上只是一個函數(shù),它借助閉包的語法去修改一個函數(shù)(又稱被裝飾函數(shù))的行為,即decorator其實是個閉包函數(shù),該函數(shù)以被裝飾函數(shù)名(這個函數(shù)名其實是一個函數(shù)對象的引用)作為入?yún)?,在閉包內(nèi)修改被裝飾函數(shù)的行為后,返回一個新的函數(shù)對象。
特別說明:decorator并非必須以函數(shù)形式出現(xiàn),它可以是任何可被調(diào)用的對象,例如它也可以class形式出現(xiàn),參見這篇文章給出的例子。
在定義好函數(shù)裝飾器的前提下,當外部調(diào)用這個被裝飾函數(shù)時,decorator的語法糖會由Python解釋器解釋為先執(zhí)行裝飾器函數(shù),然后在裝飾器返回的新函數(shù)對象上繼續(xù)執(zhí)行其余語句。
來個實例分析一下:

#!/bin/env python
#-*- encoding: utf-8 -*-

def wrapper(fn):
 def inner(n, m):
  n += 1
  print 'in inner: fn=%s, n=%s, m=%s' % (fn.__name__, n, m)
  return fn(n, m) + 6 // 這里有return且返回值為int對象
 return inner

@wrapper
def foo(n, m):
 print 'in foo: n=%s, m=%s' % (n, m)
 return n * m

print foo(2, 3)

上面的示例中,foo通過@wrapper語法糖聲明它的裝飾器是wrapper,在wrapper中,定義了嵌套的inner函數(shù)(該函數(shù)的參數(shù)列表必須與被裝飾函數(shù)foo的參數(shù)列表保持一致),裝飾器wrapper修改foo的行為后,返回inner(注意:由于inner的返回值是個int對象,故wrpper最終返回的也是個int對象)。
調(diào)用foo(2, 3)時,Python解釋器先調(diào)用wrapper對foo做行為改寫,然后返回int對象,不難推測,上述代碼的執(zhí)行結(jié)果如下:

in inner: fn=foo, n=3, m=3
in foo: n=3, m=3
foo(2, 3)=15

相關文章

  • python利用sklearn包編寫決策樹源代碼

    python利用sklearn包編寫決策樹源代碼

    這篇文章主要為大家詳細介紹了python利用sklearn包編寫決策樹源代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • 利用python爬取m3u8格式視頻的具體實現(xiàn)

    利用python爬取m3u8格式視頻的具體實現(xiàn)

    之前爬取的視頻都是mp4格式的,直接用requests請求就可以直接爬取,最近公司安排了一個小任務,需要爬取m3u8這種格式的視頻,下面這篇文章主要給大家介紹了關于利用python爬取m3u8格式視頻的相關資料,需要的朋友可以參考下
    2022-08-08
  • 使用Python實現(xiàn)FTP文件自動傳輸腳本

    使用Python實現(xiàn)FTP文件自動傳輸腳本

    這篇文章主要為大家詳細介紹了如何使用Python實現(xiàn)FTP文件自動傳輸腳本,文中的示例代碼講解詳細,具有一定的借鑒價值,感興趣的小伙伴可以了解下
    2023-12-12
  • Jupyter Notebook調(diào)用指定的虛擬環(huán)境的實現(xiàn)示例

    Jupyter Notebook調(diào)用指定的虛擬環(huán)境的實現(xiàn)示例

    本文主要介紹了Jupyter Notebook調(diào)用指定的虛擬環(huán)境的實現(xiàn)示例,,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-07-07
  • 基于Python制作簡易的windows修改器

    基于Python制作簡易的windows修改器

    現(xiàn)在應該大部分人都使用win11系統(tǒng)吧,win11其實挺好用哈,只是有一點不好用,就是右鍵的菜單,今天做個小程序,就是應該修改win11的一個應用程序,感興趣的可以了解一下
    2022-08-08
  • 解決python腳本中error: unrecognized arguments: True錯誤

    解決python腳本中error: unrecognized arguments: True錯誤

    這篇文章主要介紹了解決python腳本中error: unrecognized arguments: True錯誤,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-04-04
  • Python繪圖實現(xiàn)臺風路徑可視化代碼實例

    Python繪圖實現(xiàn)臺風路徑可視化代碼實例

    這篇文章主要介紹了Python繪圖實現(xiàn)臺風路徑可視化代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-10-10
  • Python編程中Python與GIL互斥鎖關系作用分析

    Python編程中Python與GIL互斥鎖關系作用分析

    GIL互斥鎖用來保護Python世界里的對象,防止同一時刻多個線程執(zhí)行Python字節(jié)碼,確保線程安全,但也導致Python線程無法利用多核CPU優(yōu)勢,本文來探討Python將來是否有可能去除GIL
    2021-09-09
  • Pytorch轉(zhuǎn)tflite方式

    Pytorch轉(zhuǎn)tflite方式

    這篇文章主要介紹了Pytorch轉(zhuǎn)tflite方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-05-05
  • python 調(diào)用釘釘機器人的方法

    python 調(diào)用釘釘機器人的方法

    今天小編就為大家分享一篇python 調(diào)用釘釘機器人的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-02-02

最新評論