【Python】閉包的實現原理,如何在內部函數修改外部函數的變量

什麼是閉包?

  • 閉包是指在一個函數中定義了一個另外一個函數,內函數裏運用了外函數的臨時變量,並且外函數的返回值是內函數的引用,這樣就構成了一個閉包 。
  • 閉包的使用,可以隱藏內部函數的工作細節,只給外部使用者提供一個可以執行的內部函數的引用。
  • 注意:裝飾器是用於拓展已有函數功能的一種函數,這個函數的特殊之處在於它的返回值也是一個函數,實際上就是利用閉包語法實現的。

在Pyhton中,函數也是一個對象,在函數操作中,函數對象也可以當成一個參數或一個返回值進行返回, 當程序內或程序外拿到參數的引用後就可以直接使用這個函數。
那閉包到底是什麼呢?現在就來實現一個簡單的閉包

實現一個閉包

def myFunc():
    n = '我是myFunc()函數的變量n'
    def show():
        print('內函數show()輸出:', n)
    return show

s = myFunc()
s()

# 運行效果
# 內函數show()輸出: 我是myFunc()函數的變量n

表層

將 show 函數封裝在了 myFunc 函數內部,使外部不可見,不能使用 show 函數,隱藏了實現細節。

內部

  • n 是一個 myFunc 函數中的局部變量,正常情況下 myFunc 函數執行結束後,n 就會被釋放。
  • 但是現在因爲 callFunc 函數中返回了 show 函數,show 函數在外部還會再執行,所以程序會將 show 函數所需的執行環境保存下來。
  • 這種形式就是閉包

如何在內部函數修改外部函數的變量

這裏有個注意點:修改不等於賦值,修改是改變原變量的引用,而賦值是讓變量指向了新的引用,並沒有改變原變量的引用。
通過代碼來看吧:
首先看賦值:

def myFunc():
    m = 1
    n = 2
    def show():
        print('m的值爲:', m)
        
        n = 10
        print('n的值爲:', n)
    return show

s = myFunc()
s()

# 執行效果:
# m的值爲: 1
# n的值爲: 10

可見,賦值操作沒有任何問題,那修改呢?

def myFunc():
    m = 1
    n = 2
    def show():
        print('m的值爲:', m)
        # nonlocal n #如果不加會報錯。
        n += 10
        print('n的值爲:', n)
    return show

s = myFunc()
s()

執行效果:
在這裏插入圖片描述
將代碼中的註釋‘# nonlocal n #如果不加會報錯。’打開:
在這裏插入圖片描述

nonlocal

  • 如果在閉包的內部函數中直接使用外部函數的變量時,不需要任何操作,直接使用就可以了。
  • 但是如果要修改外部變量的值,需要將變量聲明爲 nonlocal
  • nonlocal 聲明變量爲非本地變量,如果確定在程序要修改外部變量,那麼建議將 nonlocal 寫在內部函數的第一行。

總結

閉包就是在一個外部函數中定義了一個內部函數,並且在內部函數中使用了外部函數的變量,並返回了內部函數。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章