通過一段簡單的代碼理解python中的閉包

通過一段簡單的代碼理解python中的閉包

引例

  • 假設學校每個學期有n次考試,我們需要寫一個程序來計算一個學生的前a(a<=n)次考試的平均成績。
  • 每出一次成績,只需要將當次的成績輸入電腦,就可以得到平均成績
  • 代碼運行在學校的服務器上,於是有了以下代碼:
def caculate(score):
    sum = 0
    ls.append(score)
    for i in ls:
        sum += i
    return sum/len(ls)


if __name__ == '__main__':
    ls = []
    print(caculate(10))
    print(caculate(12))
    print(caculate(15))

分析

  • 上面的代碼可以解決問題,但仍然存在一個問題,那就是將存放成績的列表當做全局變量,這樣做會有一個問題,就是可以被很輕易地篡改。一旦被有心人篡改會非常嚴重,所以我們需要隱藏列表。
  • 隱藏列表,無非就是將列表放在函數作用域中,這樣就不能被輕易訪問了。
  • 但問題也會同樣存在,函數的內存空間是在執行時被創建的,並且一旦執行結束,函數所佔的內存就會被回收,那麼保存在函數中的列表中的數據也會被清空。

使用閉包的代碼:

def average():
    # 用於儲存每一次的成績
    ls = []
    # 向列表中添加數據,並計算平均值
    def caculate(score):
        sum = 0
        ls.append(score)
        print(ls)
        for i in ls:
            sum += i
        return sum/len(ls)
    return caculate



if __name__ == '__main__':
    caculate = average()
    print(caculate(10))
    print(caculate(15))
    print(caculate(20))
    
# 打印結果
[10]
10.0
[10, 15]
12.5
[10, 15, 20]
15.0
  • 我們可以看到,成績列表中的數據並沒有被清除

原理

  • 因爲caculate函數使用了average函數中的ls變量,所以average函數產生的內存空間會一直存在(這其實就是閉包),等待caculate函數使用,而average函數返回了caculate函數的引用(函數名),這樣我們就可以在全局中通過caculate函數操作ls變量,
  • 雖然也可以操作但只能添加數據,而不能隨意更改數據,這樣安全性就得到了提升
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章