首頁 >後端開發 >Python教學 >Python中閉包Closure是什麼?有哪些應用?

Python中閉包Closure是什麼?有哪些應用?

不言
不言轉載
2018-10-13 14:53:212471瀏覽

這篇文章帶給大家的內容是關於Python中閉包Closure是什麼?有哪些應用?有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

一、函數以返回值

#介紹「閉包」之前,先了解函數作為傳回值的情況。
高階函數除了可以接收函數當參數外,還可以把函數當作結果值回傳。例如先前介紹的裝飾器中,就出現了將函數當作傳回值。

二、閉包

1、產生閉包的條件、作用

什麼是閉包?
當在函數中嵌套另一個函數時,如果內部函數引用了外部函數的變量,則可能產生閉包。
所以閉包產生的三個條件(缺一不可)

  • #1、必須嵌套一個內部函數

  • 2、內部函數必須引用外部函數的變數

  • 3、外部函數必須傳回內部函數

那為什麼要試用閉包,閉包的作用呢?

  • 1、閉包可以根據外部函數的局部變數來得到不同的結果

  • 2、當閉包執行完成後,仍可以保持目前的運行環境,執行結果依賴於函數上一次的運行結果

#2、閉包舉例

栗子一:求序列總和

>>> def calc_sum(*args):
...     ax = 0
...     for n in args:
...         ax = ax + n
...     return ax  # 返回变量
...
>>> calc_sum(1,2,3)
6

但是,現在如果要求不需要立即取得求和結果,而是在後面的程式碼中,根據需要再計算,該怎麼弄呢?
我們可以不傳回求和的結果,而傳回求和的函數,如下:

>>>def lazy_sum(*args):
...    def sum():            # sum()是内部函数,可以利用外部函数的参数
...        ax = 0
...        for n in args:    # sum()中使用外部函数的局部变量
...            ax = ax + n 
...        return ax
...    return sum            # 形成闭包,此时,*args保存在返回的函数中
...
>>>f = lazy_sum(1,3,5,7,9)
>>>f          # 此时返回的是求和函数
>>> f()       # 调用函数f()时,才真正计算求和的结果
25

注意:

lazy_sum()函數的內部執行順序,當f時,執行到return sum處,*args保存在回傳函數中,傳回的是sum()函數。執行f()時,相當於執行sum(),且包含*args。

當我們呼叫lazy_sun()時,每次都會回傳一個新的函數,即使傳入相同的參數,但是f()呼叫結果不影響。

我們來驗證第二點:

# 但是调用 f1() 与f2()的调用结果互不影响
>>> f1 = lazy_sum(1,3,5,7,9)
>>> f2 = lazy_sum(1,3,5,7,9)
>>> f1
<function lazy_sum.<locals>.sum at 0x013DD618>
>>> f2
<function lazy_sum.<locals>.sum at 0x02F92DF8>
>>> f1 == f2
False
>>> f1() == f2()
True
>>> f1()
25
>>> f2()
25
>>> id(f1())
1627215984
>>> id(f2())
1627215984

說明:f1與f2回傳函數的位置不一樣,所以f1==f2回傳結果為False。
但是不影響最後的執行結果,f1()與f2()的執行結果均為25,且用id()進行查看,指向是同一塊區域。

栗子二:

def count():
    fs = []
    for i in range(1, 4):
        def f():         # 返回函数f()放在循环里
            return i*i
    fs.append(f)
    return fs
f1, f2, f3 = count()

實際執行結果為:f1=9 f2=9 f3=9
可能與實際想的([1,4,9])有點不一樣。因為f()函數放在了for迴圈裡,只有當迴圈結束後,最後才回傳i=3的執行結果9。
所以回傳函數最好不要引用任何循環變量,或是後續可能變化的量。那如何來修改呢?

def count():
    def f(j):
        def g():
            return j*j      # 形成闭包
        return g
    fs = []
    for i in range(1, 4):
        fs.append(f(i))      # 一个i值进入后,f(i)立刻被执行,并加入到fs中
    return fs

f1, f2, f3 = count()  # 返回函数g没有引用j

最後結果:[1,4,9] 即f1=1 f2=4 f3=

三、匿名函數lambda




  • ##定義:匿名函數指一類無需定義標識符函數名的函數或子程序。 Python允許使用lambda關鍵字創造匿名函數。

    語法:lambda 參數:表達式
  •   或lambda 形參1,…,形參n : function(形參),入參1,…,入參n
    #注意:1、lambda函數可以接收任意多個參數且傳回單一表達式的值;
  •   2、lambda中不能包含指令,傳回的表達式不能超過一個。

    優點:1、可以省去定義函數的過程,精簡程式碼;
  •   2、對於一些抽象的、不會重複使用的函數可以用lambda來定義。
######範例:###
>>> list( map( lambda x: x*x ,[1,2,3] ) )
[1, 4, 9]
###其中###lamdba x : x*x### 實作的是:###def f(x): return x*x#### 的功能。 ############可以把匿名函數賦值給一個變量,再利用變數呼叫該函數。例如:#########
>>> f = lambda x:x*x  
>>> f(5) # 调用
>>> g = lambda x,y=2 : x*y
>>> g(2,4)
8
>>> g(2)    # 默认y=2
4
########可以把匿名函數當作傳回值傳回,例如:#########
return lambda x:x*x

以上是Python中閉包Closure是什麼?有哪些應用?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除