成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Python為什么引入這兩個關鍵詞:global和nonlocal

開發 后端
本文通過分析函數對全局變量和閉包變量的讀、寫操作,借助于反匯編字節碼分析,認清了 global 和 nonlocal 關鍵字的用法,對其引入和作用有了較為深刻認識。

[[408478]]

本文轉載自微信公眾號「Python中文社區」,作者鞏慶奎。轉載本文請聯系Python中文社區公眾號。

啥是 global 和 nonlocal

Python 支持的關鍵詞里,global 和 nonlocal 初學者接觸的少,不知道是做什么用的;一些人雖然知道它們的作用,但對為什么要引入這兩個關鍵詞則有些不知其所以然。

粗淺地說,global 和 nonlocal 是為了在函數中修改全局和閉包變量而引入的關鍵字。

本文用代碼一點點分析引入 global 和 nonlocal 的原因。

一個奇怪的現象

下面,讓我們做一個測試。

  1. g =1 
  2. def fun(): 
  3.     g = 2 
  4.     return g  
  5. print(fun(),g) 

一般地,我們認為結果應該為 2,2。這一點學過其他語言如 Java、c 的同學尤其認同。

但讓我們跑起來,可以看到結果為 2,1。也就是說,函數沒有改變全局變量 g。

這很奇怪,究其原因是因為:

  • Python 認為所有 = 賦值都是在當前作用域新建變量。
    • 當我們在程序中 g = 1 時,表示當前全局作用域建立 g,賦值 1。
    • 當我們在函數中 g = 2 時,表示當前局部作用域建立 g,賦值 2。

使用 dis.dis(fun) 分析 fun 函數源代碼:

  1. 16           0 LOAD_CONST               1 (2) 
  2.               2 STORE_FAST               0 (g) 
  3.  17           4 LOAD_FAST                0 (g) 
  4.               6 RETURN_VALUE 

可見,第 2 條指令 STORE_FAST,這是存儲到局部變量的命令。

所以,函數中實際操作的是局部變量。

還有更甚的例子如下,大家猜測下執行結果。

  1. g =1 
  2. def fun(): 
  3.     g += 1 
  4.     return g 
  5. print(fun(),g)  

根據上文,我們知道函數不會改變全局變量 g,那么結果應該是 2,1,這次總算對了吧?

很抱歉,當執行到 g += 1 時,系統報錯:UnboundLocalError: local variable 'g' referenced before assignment。

仔細觀察錯誤,local variable 'g',這里的 g 仍然被視為局部變量:沒有定義(=賦值),就直接 inplace add,當然要報錯。

也就是說,所有在局部作用域中對全局變量的賦值、原位賦值都會失敗。唯有如下函數給我們帶來一絲安慰。

  1. g =1 
  2. def fun(): 
  3.     return g 
  4. print(fun(),g)  

結果 1,1,總算還有個正常的:在局部作用域中引用全局作用域變量正常。

那當我必須修改全局變量時,該怎么辦呢?

global 的引入和分析

這就是 global 引入的理由了,將全局變量擴展到函數中來,使函數可以修改全局變量。

  1. g =1 
  2. def fun(): 
  3.     global g 
  4.     g = 2 
  5.     return g 
  6. print(fun(),g)  

結果為 2,2,函數修改了全局變量。我們來看 dis.dis(fun) 的反匯編代碼。

  1. 37           0 LOAD_CONST               1 (2) 
  2.              2 STORE_GLOBAL             0 (g) 
  3. 38           4 LOAD_GLOBAL              0 (g) 
  4.              6 RETURN_VALUE 

第 2 條指令,STORE_GLOBAL 是將常量 2 賦值給全局變量 g,異于上例中的 STORE_FAST指令對局部變量操作。

故此,我們得出結論:當在函數中讀取全局變量時,可以直接使用。但如果需要修改全局變量值,則需要在變量前加上 global 來修飾。

nonlocal 的引入

同樣地,當我們書寫嵌套函數,需要對閉包中的變量進行修改操作時,我們也需要引入 nonlocal 關鍵字。

如下函數中,我們定義了閉包,閉包中的變量 e,試圖在內嵌函數中進行修改,但沒有使用 nonlocal 關鍵字聲明 e。

  1. def outer(): 
  2.     e = 1 
  3.     def inner(): 
  4.         e = 2 
  5.         return e 
  6.     return inner 

參照上例,我們知道這種修改是徒勞的——因為看反匯編代碼 dis.dis(outer()) 可知:

  1. 63           0 LOAD_CONST               1 (2) 
  2.              2 STORE_FAST               0 (e) 
  3. 64           4 LOAD_FAST                0 (e) 
  4.              6 RETURN_VALUE 

第 2 條指令 STORE_FAST,操作局部變量,也就是說 inner 里的 e,仍然被視為局部變量。

雷同于上例的 global,這里使用 nonlocal 來在內嵌函數 inner 中修改閉包變量 e。

  1. def outer(): 
  2.     e = 1 
  3.     def inner(): 
  4.         nonlocal e 
  5.         e = 2 
  6.         return e 
  7.     return inner 

查看此時的反匯編代碼 dis.dis(outer()) 可知:

  1. 78           0 LOAD_CONST               1 (2) 
  2.              2 STORE_DEREF              0 (e) 
  3. 79           4 LOAD_DEREF               0 (e) 
  4.              6 RETURN_VALUE 

第 2 條指令 STORE_DEREF,操作的是閉包變量,也就是說 inner 里的 e,是可以修改的閉包中的 e。

總結

本文通過分析函數對全局變量和閉包變量的讀、寫操作,借助于反匯編字節碼分析,認清了 global 和 nonlocal 關鍵字的用法,對其引入和作用有了較為深刻認識。

 

作者:鞏慶奎,大奎,對計算機、電子信息工程感興趣。

 

責任編輯:武曉燕 來源: Python中文社區
相關推薦

2011-06-20 14:32:59

關鍵詞

2011-06-07 18:45:41

關鍵詞

2011-06-14 19:11:38

關鍵詞

2016-06-02 11:02:02

機器學習

2011-06-16 17:54:25

關鍵詞

2013-08-26 15:43:40

AppStore關鍵詞開發者應用選取關鍵詞

2011-05-25 17:58:00

2011-06-21 16:11:04

SEO關鍵詞

2019-12-22 13:48:26

退休科技行業大佬

2011-05-25 17:38:56

關鍵詞

2023-01-13 16:57:50

SpringBoot配置核心

2020-12-10 10:32:33

區塊鏈比特幣數字貨幣

2016-01-06 10:05:20

2013-04-16 21:52:27

IBM云計算開源

2011-05-10 10:39:07

關鍵詞SEO

2011-06-19 12:20:47

長尾關鍵詞

2012-03-20 22:19:16

Linux

2011-06-14 10:01:03

長尾關鍵詞

2009-11-03 09:02:59

Windows 7蘋果競爭

2011-07-22 15:48:46

SEO
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久精品网| 99re视频在线 | 北条麻妃一区二区三区在线观看 | 国产在线一区观看 | 日韩一区二区三区精品 | 国产高清精品一区二区三区 | 中文字幕国产视频 | 伊人久麻豆社区 | 欧美成人视屏 | 中文一区 | 久久久久久黄 | 国产亚洲欧美另类一区二区三区 | 成人免费观看男女羞羞视频 | 亚洲精品3 | 国产免费一区二区三区最新6 | 国产精品国产成人国产三级 | 日本久久网站 | 亚洲精品中文字幕在线 | 日本欧美国产 | 精品视频一区二区三区四区 | 精品国产乱码久久久久久牛牛 | 成人综合视频在线观看 | 青青久久 | 亚洲福利| 日韩免费av | 欧美精品一区二区三区四区 在线 | 欧美一级特黄aaa大片在线观看 | 亚洲成人精品 | 亚洲 中文 欧美 日韩 在线观看 | 天天干人人 | 久久久91精品国产一区二区三区 | 国产资源一区二区三区 | 日韩国产在线 | 欧美日韩视频在线播放 | 日韩在线视频精品 | 久久久激情视频 | 国产精品精品 | 日韩中文字幕视频在线观看 | 亚洲一区精品视频 | 97国产在线视频 | 国产丝袜一区二区三区免费视频 |