網站首頁 編程語言 正文
1 什么是閉包
在 Python 中,閉包是一種特殊的函數,它能夠記住它所在的環境(也稱作上下文)。這意味著閉包能夠訪問定義它的作用域中的變量。閉包通常用于封裝數據和提供對外部訪問的接口。
在 Python 中使用閉包有以下幾點好處:
- 保存狀態:閉包可以保存外部函數的狀態,以便在內部函數中使用。
- 簡化代碼:閉包可以簡化代碼結構,使得復雜的邏輯變得簡單易懂。
- 模塊化編程:閉包可以更好地封裝代碼,提高代碼的可重用性。
- 保證函數線程安全:閉包可以保證函數的線程安全性,避免全局變量被多線程修改。
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是外部函數,它返回一個內部函數inner_func。內部函數使用了外部函數的變量x,并且在被調用時使用了參數y。因此,當我們調用outer_func(10)時,它返回了一個閉包(即inner_func),它記錄了x=10的值。之后,我們可以調用這個閉包,并傳入參數y來計算結果。
3 什么是閉包陷阱
Python中的閉包陷阱指的是在閉包中引用了變量時,如果該變量在閉包外部被修改,則閉包內部的值也會改變。這可能會導致程序的錯誤或意外行為。
4 閉包陷阱代碼實例
請對比以下兩組代碼
4.1 第一組代碼實例
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])
在執行代碼時,首先i
的在range(3)
中獲取的值為0,接下來執行l.append(inner)
。這里inner并沒有括號,所以inner本身不會被執行,而是在l中添加了一個inner函數對象。并且inner函數的形參i_
默認值為0。
接下來,在for循環的作用下,l
又被重復添加了兩次inner對象,其中i_
的默認值分別為1和2。
執行完closure1
后,我們使用列表推到式去遍歷l1
。
列表推導式中的i()
使得inner對象被執行。因為i()
中未傳入任何參數,所以其中的i_
使用了我們定義的默認參數:0,1,2。在執行完inner函數后,這些數字變成了0,1,4。因此最終的輸出即為[0,1,4] 。
以上是一段正常的非閉包代碼。
4.2 第二組代碼實例
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])
這一組代碼和上面一組代碼沒有很大的區別,唯一的差異是,這一組代碼的inner并未傳入形參i_
。inner中的i
直接取自外部。
因此,在執行closure2
中的for循環時,l中依然會被傳入3個inner函數對象,唯一的區別是傳入的對象沒有指定形參的默認值。
在執行[i() for i in l2]這個列表推到式時,inner函數并未找到對i的賦值,因此回到外部的closure2中去尋找,并找到了i的值為3。
因此,對于這段代碼,每一個inner函數對象的輸出都是4。
很明顯這并不是我們想要的結果,這就是一個典型的閉包陷阱。
總結
原文鏈接:https://blog.csdn.net/nkufang/article/details/128759484
- 上一篇:C#中[]的幾種用法示例代碼_C#教程
- 下一篇:淺談C#中[]的幾種用法_C#教程
相關推薦
- 2022-11-18 React中props使用教程_React
- 2022-03-28 一篇文章帶你學習python的函數與類_python
- 2022-12-22 Flutter?Widget?之StatefulBuilder構建方法詳解_Android
- 2022-06-02 Consul的HTTP?API和使用方法_云計算技術
- 2022-07-06 Python函數之iterrows(),iteritems(),itertuples()的區別說明_
- 2022-05-25 String.isEmpty() 方法使用報空指針異常?那怎么才能更好的判斷String返回值為空的
- 2022-10-18 AJAX跨域問題解決方案詳解_AJAX相關
- 2022-05-10 開發跨域問題的解決
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支