網站首頁 編程語言 正文
理解閉包之前,我們首先需要理解什么是嵌套函數(nested functions)以及非局部(nonloca)關鍵字
嵌套函數
- 在另一個函數中定義的函數稱為嵌套函數。
- 嵌套函數可以訪問 這個封閉范圍域內的 變量。
- 在python中,這些非局部變量只可以在他們的作用域范圍內訪問。
嵌套函數的例子:
#Python program to illustrate #nested functions def outerFunction(text): text = text #該函數定義在函數之內,作為一個內部函數 def innerFunction(): print(text) #out函數中,調用這個內部函數 innerFunction() if __name__ == '__main__': outerFunction('Hey !')
嵌套函數中變量的范圍
在一個函數中訪問全局變量之前已經說過了,但是怎么在一個內部函數中訪問外部函數的變量?
def f1(): #f1的變量 s = 'hello' def f2(): #f2()內部使用f1的變量 print(s) f2() f1()
這種訪問方式和 函數內訪問全局變量很類似。
現在我想要在內部函數改變外部函數的變量要怎么做?
def f1(): #f1的變量 s = 'hello' def f2(): #f2()內部試圖改變f1的變量 s = 'hi hi hi' print(s) f2() print(s) #調用f1() f1()
在f2()
內部通過s = 'hi hi hi'
試圖將外部函數的變量值s
改變。
但是其實是在f2()
內部重新創建了一個新的變量也叫s
,所以完全不會對外部的s
有影響。
這和函數內部改變全局變量是類似的,不加global
,只是創建了一個同名變量。
那么同樣使用global
行不行?
def f1(): #f1的變量 s = 'hello' def f2(): #f2()內部試圖使用global改變f1的變量 global s s = 'hi hi hi' #實際是在f2()中創建了一個全局變量 print(s) f2() print(s) #調用f1() f1()
結果是完全沒有變化的,
global s
實際上是在f2()
內部聲明s
是一個全局變量,是整個程序都可以使用的,它和f1()
中的s
不是同一個。我們可以在函數外輸出它:
那么如何通過內部函數改變外部函數的變量值呢?其中一種方法是使用nonlocal
關鍵字:
def f1(): #f1的變量 s = 'hello' def f2(): #f2()使用nonlocal改變f1的變量 nonlocal s s = 'hi hi hi' print(s) f2() print(s) #調用f1() f1()
在f2()函數內部成功的修改了f1()函數中的變量s的值
nonlocal
nonlocal 關鍵字被用來在最近的范圍域中引用變量, 在局部變量和全局變量上使用不起作用,用于在全局范圍和本地局部范圍之外的另一個范圍內引用變量。nonlocal關鍵字常常被用在嵌套函數中引用 父函數中的變量。
使用nonlocal的優點
- 幫助我們訪問上層作用域中的變量
- 引用的變量被重復使用,因此該變量的內存地址也被重復適使用,所以可以將局部變量保存在內存中
缺點
- nonloca關鍵字不可以用來引用全局變量和局部變量
- nonloca關鍵字只能用在嵌套結構中
舉例
使用nonlocal關鍵字修改父函數中的變量
def foo(): name = 'hello' def bar(): nonlocal name #修改父函數的變量 name = 'hi hi' print(name) #調用bar() bar() #父函數foo()內輸出name print(name) #調用foo() foo()
如果使用nonlocal 修改全局變量會怎么樣?
#全局變量 global_name = 'hello' #外部函數 def f1(): #內部函數 def f2(): #使用nonlocal 聲明,嘗試使用nonlocal 引用全局變量 nonlocal global_name global_name = 'hi hi'#嘗試 修改 print(global_name) #掉用f2() f2() f1() print(global_name)
報錯信息顯示:沒有叫做global_name
的nonlocal
變量,這是因為:
nonlocal
是用在嵌套結構中,用來引用父函數中的局部變量的,但是父函數f1()
中沒有叫做global_name
的局部變量,對于函數外部的全局變量global_name
來說,使用nonlocal
是無法引用的,所以python解釋器找不到global_name
,自然出錯。
多層嵌套中的nonlocal
def f1(): name = 'f1' def f2(): name = 'f2' def f3(): #nonlocal 修改父函數的變量,即f2()的name nonlocal name print(name) #輸出f2 使用的是f2中的name name = 'f3' #對f2中的name修改 print(name) #輸出f3 修改成功 f3() print(name)#輸出f3,雖然是f2中的name,但是在f3中修改了 f2() print(name)#輸出f1,f1的name,沒有被使用 f1()
所以在多層嵌套的結構成,nonlocal關鍵字會尋找最近的上層,也就是父函數,而不是更上層的爺爺函數。
嵌套函數中局部變量的重用
def counter(): #c是局部變量 c = 0 def count(): #使用上層函數中的c nonlocal c c += 1 return c return count
調用外部counter()
函數,正常來說,函數調用結束后,內部的局部變量會被銷毀,但是由于counter()
內部嵌套的count()
使用了nonlocal
來使用父函數的局部變量c
,所以c
是被重用了,即使外層函數調用結束了,c
并沒有被銷毀。
參考:
Python Inner Functions
Python nonlocal Keyword
原文鏈接:https://blog.csdn.net/weixin_42576837/article/details/125530032
相關推薦
- 2022-09-03 C#設計模式之建造者模式_C#教程
- 2022-05-11 為什么 MyBatis 里,Mapper 中的方法不能被重載
- 2022-11-06 Android?ViewPager2?使用及自定義指示器視圖實現_Android
- 2022-07-16 mybatis的相同攔截器—切面執行的順序
- 2022-05-04 C#設計模式之單例模式_C#教程
- 2022-12-24 Docker網絡模型以及容器通信詳解續篇_docker
- 2022-06-27 教你用Python按順序讀取文件夾中文件_python
- 2022-11-26 利用Python讀取Excel表內容的詳細過程_python
- 最近更新
-
- 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同步修改后的遠程分支