Python閉包與閉包陷阱舉例詳解
1 什么是閉包
在 Python 中,閉包是一種特殊的函數(shù),它能夠記住它所在的環(huán)境(也稱作上下文)。這意味著閉包能夠訪問定義它的作用域中的變量。閉包通常用于封裝數(shù)據(jù)和提供對外部訪問的接口。
在 Python 中使用閉包有以下幾點(diǎn)好處:
- 保存狀態(tài):閉包可以保存外部函數(shù)的狀態(tài),以便在內(nèi)部函數(shù)中使用。
- 簡化代碼:閉包可以簡化代碼結(jié)構(gòu),使得復(fù)雜的邏輯變得簡單易懂。
- 模塊化編程:閉包可以更好地封裝代碼,提高代碼的可重用性。
- 保證函數(shù)線程安全:閉包可以保證函數(shù)的線程安全性,避免全局變量被多線程修改。
2 閉包示例代碼
代碼示例如下:
def outer_func(x): def inner_func(y): return x + y return inner_func closure = outer_func(10) print(closure(5)) # 15
這是一個閉包的示例代碼,其中outer_func是外部函數(shù),它返回一個內(nèi)部函數(shù)inner_func。內(nèi)部函數(shù)使用了外部函數(shù)的變量x,并且在被調(diào)用時使用了參數(shù)y。因此,當(dāng)我們調(diào)用outer_func(10)時,它返回了一個閉包(即inner_func),它記錄了x=10的值。之后,我們可以調(diào)用這個閉包,并傳入?yún)?shù)y來計算結(jié)果。
3 什么是閉包陷阱
Python中的閉包陷阱指的是在閉包中引用了變量時,如果該變量在閉包外部被修改,則閉包內(nèi)部的值也會改變。這可能會導(dǎo)致程序的錯誤或意外行為。
4 閉包陷阱代碼實(shí)例
請對比以下兩組代碼
4.1 第一組代碼實(shí)例
def closure1(): l = [] for i in range(3): def inner(i_=i): return i_**2 l.append(inner) return l l1 = closure1() print([i() for i in l1])
在執(zhí)行代碼時,首先i
的在range(3)
中獲取的值為0,接下來執(zhí)行l.append(inner)
。這里inner并沒有括號,所以inner本身不會被執(zhí)行,而是在l中添加了一個inner函數(shù)對象。并且inner函數(shù)的形參i_
默認(rèn)值為0。
接下來,在for循環(huán)的作用下,l
又被重復(fù)添加了兩次inner對象,其中i_
的默認(rèn)值分別為1和2。
執(zhí)行完closure1
后,我們使用列表推到式去遍歷l1
。
列表推導(dǎo)式中的i()
使得inner對象被執(zhí)行。因?yàn)?code>i()中未傳入任何參數(shù),所以其中的i_
使用了我們定義的默認(rèn)參數(shù):0,1,2。在執(zhí)行完inner函數(shù)后,這些數(shù)字變成了0,1,4。因此最終的輸出即為[0,1,4] 。
以上是一段正常的非閉包代碼。
4.2 第二組代碼實(shí)例
def closure2(): l = [] for i in range(3): def inner(): return i**2 l.append(inner) print(inner.__closure__) return l l2 = closure2() print([i() for i in l2])
這一組代碼和上面一組代碼沒有很大的區(qū)別,唯一的差異是,這一組代碼的inner并未傳入形參i_
。inner中的i
直接取自外部。
因此,在執(zhí)行closure2
中的for循環(huán)時,l中依然會被傳入3個inner函數(shù)對象,唯一的區(qū)別是傳入的對象沒有指定形參的默認(rèn)值。
在執(zhí)行[i() for i in l2]這個列表推到式時,inner函數(shù)并未找到對i的賦值,因此回到外部的closure2中去尋找,并找到了i的值為3。
因此,對于這段代碼,每一個inner函數(shù)對象的輸出都是4。
很明顯這并不是我們想要的結(jié)果,這就是一個典型的閉包陷阱。
總結(jié)
到此這篇關(guān)于Python閉包與閉包陷阱舉例的文章就介紹到這了,更多相關(guān)Python閉包與閉包陷阱內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用spyder3調(diào)試python程序的實(shí)現(xiàn)步驟
本文主要介紹了使用spyder3調(diào)試python程序的實(shí)現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-12-12python學(xué)習(xí)之hook鉤子的原理和使用
這篇文章主要為大家詳細(xì)介紹了python學(xué)習(xí)之hook鉤子的原理和使用,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-10-10python 實(shí)現(xiàn)定時任務(wù)的四種方式
這篇文章主要介紹了python 實(shí)現(xiàn)定時任務(wù)的四種方式,幫助大家更好的理解和學(xué)習(xí)使用python,感興趣的朋友可以了解下2021-04-04python格式化輸出保留2位小數(shù)的實(shí)現(xiàn)方法
這篇文章主要介紹了python格式化輸出保留2位小數(shù)的實(shí)現(xiàn)方法,需要的朋友可以參考下2019-07-07Python入門教程(四十)Python的NumPy數(shù)組創(chuàng)建
這篇文章主要介紹了Python入門教程(四十)Python的NumPy數(shù)組創(chuàng)建,NumPy 用于處理數(shù)組,NumPy 中的數(shù)組對象稱為 ndarray,我們可以使用 array() 函數(shù)創(chuàng)建一個 NumPy ndarray 對象,需要的朋友可以參考下2023-05-05Mac在python3環(huán)境下安裝virtualwrapper遇到的問題及解決方法
這篇文章主要介紹了Mac在python3環(huán)境下安裝virtualwrapper遇到的問題及解決方法,我在使用mac安裝virtualwrapper的時候遇到了問題,搞了好長時間,,在這里總結(jié)一下分享出來,供遇到相同的問題的朋友使用,少走些彎路,需要的朋友可以參考下2019-07-07