網站首頁 Python教程 正文
閉包必須滿足以下3個條件:
- 必須有一個內嵌函數(shù)
- 內嵌函數(shù)必須應用外部函數(shù)的變量
- 外部函數(shù)的返回值必須是內嵌函數(shù)
關于請看下面代碼:
def multipliers():
return [lambda x : i*x for i in range(4)]
print ([m(2) for m in multipliers()] )
"""
[6, 6, 6, 6]
"""
為什么輸出結果為[6, 6, 6, 6],這段代碼相當于
def multipliers():
funcs = []
for i in range(4):
def bar(x):
return x*i
funcs.append(bar)
return funcs
print ([m(2) for m in multipliers()] )
"""
[6, 6, 6, 6]
"""
運行代碼,解釋器碰到了一個列表解析,循環(huán)取multipliers()函數(shù)中的值,而multipliers()函數(shù)返回的是一個列表對象,這個列表中有4個元素,
每個元素都是一個匿名函數(shù)(實際上說是4個匿名函數(shù)也不完全準確,其實是4個匿名函數(shù)計算后的值,因為后面for i 的循環(huán)不光循環(huán)了4次,
同時提還提供了i的變量引用,等待4次循環(huán)結束后,i指向一個值i=3,這個時候,匿名函數(shù)才開始引用i=3,計算結果。所以就會出現(xiàn)[6,6,6,6],
因為匿名函數(shù)中的i并不是立即引用后面循環(huán)中的i值的,而是在運行嵌套函數(shù)的時候,才會查找i的值,這個特性也就是延遲綁定)
# 為了便于理解,你可以想象下multipliers內部是這樣的(這個是偽代碼,并不是準確的):
def multipliers():
return [lambda x: 3 * x, lambda x: 3 * x, lambda x: 3 * x, lambda x: 3 * x]
因為Python解釋器,遇到lambda(類似于def),只是定義了一個匿名函數(shù)對象,并保存在內存中,只有等到調用這個匿名函數(shù)的時候,
才會運行內部的表達式,而for i in range(4) 是另外一個表達式,需等待這個表達式運行結束后,才會開始運行l(wèi)ambda 函數(shù),此時的i 指向3,x指向2
改進
def multipliers():
# 添加了一個默認參數(shù)i=i
return [lambda x, i=i: i*x for i in range(4)]
print ([m(2) for m in multipliers()] )
"""
[0, 2, 4, 6]
"""
相當于:
def multipliers():
funcs = []
for i in range(4):
def bar(x, i=i):
return x * i
funcs.append(bar)
return funcs
print ([m(2) for m in multipliers()] )
"""
[0, 2, 4, 6]
"""
添加了一個i=i后,就給匿名函數(shù),添加了一個默認參數(shù),而python函數(shù)中的默認參數(shù),
是在python 解釋器遇到def(i=i)或lambda 關鍵字時,就必須初始化默認參數(shù),
此時for i in range(4),每循環(huán)一次,匿名函數(shù)的默認參數(shù)i,就需要找一次i的引用,
i=0時,第一個匿名函數(shù)的默認參數(shù)值就是0,i=1時,第二個匿名函數(shù)的默認參數(shù)值就是1,以此類推
# 為了便于理解,你可以想象下multipliers內部是這樣的(這個是偽代碼只是為了理解):
def multipliers():
return [lambda x,i=0: i*x, lambda x,i=1: i*x, lambda x,i=2: i*x, lambda x,i=3:i*x i=3]
# x的引用是2 所以output的結果就是:[0,2,4,6]
當然你的i=i,也可以改成a=i。
def multipliers():
# 添加了一個默認參數(shù)a=i
return [lambda x, a=i: x*a for i in range(4)]
print ([m(2) for m in multipliers()] )
"""
[0, 2, 4, 6]
"""
Python的延遲綁定其實就是只有當運行嵌套函數(shù)的時候,才會引用外部變量i,不運行的時候,并不是會去找i的值,這個就是第一個函數(shù),為什么輸出的結果是[6,6,6,6]的原因。
原文鏈接:https://juejin.cn/post/7025997161649143822
相關推薦
- 2022-12-15 Redis分布式鎖如何設置超時時間_Redis
- 2023-04-29 C/C++并查集的查詢與合并實現(xiàn)原理_C 語言
- 2023-07-14 react實現(xiàn)拖拽功能
- 2022-10-10 YOLOv5改進之添加SE注意力機制的詳細過程_python
- 2024-04-06 Linux如何清理Redis中的緩存
- 2022-12-05 服務啟動項Start類型詳解_其它
- 2022-02-11 小程序如何把參數(shù)設置為全局變量
- 2022-08-02 Python+Selenium實現(xiàn)瀏覽器標簽頁的切換_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結構-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支