Python中關鍵字global與nonlocal的區別

終於下定決心學習Python了。既然從頭開始,就需要認認真真。

首先需要說的是,我是初學Python,這篇文章只是用於展示global和nonlocal關鍵字的區別,是很簡單的知識點,如果你已經學過,可以繞道。因爲不經常寫博客,而且是個Python小白,所以內容有些囉嗦。。。

注意:我使用的是Python3.6.3,可能和Python2有不同的地方,並未確認。

考慮到文章比較囉嗦,先把結論貼出來,避免浪費大家的時間:

第一,兩者的功能不同。global關鍵字修飾變量後標識該變量是全局變量,對該變量進行修改就是修改全局變量,而nonlocal關鍵字修飾變量後標識該變量是上一級函數中的局部變量,如果上一級函數中不存在該局部變量,nonlocal位置會發生錯誤(最上層的函數使用nonlocal修飾變量必定會報錯)。

第二,兩者使用的範圍不同。global關鍵字可以用在任何地方,包括最上層函數中和嵌套函數中,即使之前未定義該變量,global修飾後也可以直接使用,而nonlocal關鍵字只能用於嵌套函數中,並且外層函數中定義了相應的局部變量,否則會發生錯誤(見第一)。

接下來是得到結論的過程,有興趣的可以瀏覽一下。

我們先來看一個代碼片段,看看默認情況下輸出結果是什麼(不敢恭維CSDN顯示代碼的格式,這裏使用圖片,如果要驗證,得麻煩各位動動指頭了)。


輸出結果:


上面的代碼片段中沒有使用global或nonlocal關鍵字,是爲了看一下默認情況下的輸出結果。

可以看到變量x在三次輸出中是同一個變量(值相同,地址也相同),都是全局變量,在print函數中使用三個參數是爲了方便識別變量,第一個參數是print運行的位置,第二個參數是變量x保存的值,第三個參數是變量x保存的值的地址(這個有待考證)。

如果我們在func函數中修改x的值呢?


輸出結果:


可以看到func函數中x的值和地址都變了,但沒有影響函數外邊的x的值和地址(main1和main2的數據相同)。所以func函數內的x變量和函數外的x變量是兩個變量,而func內的x變量是局部變量,修改它的值不影響全局變量。

第一回合:在函數內部使用了與全局變量同名的變量,如果不對該變量賦值(修改變量),那麼該變量就是全局變量,如果對該變量進行賦值,那麼該變量就是局部變量。

如果我們想在func函數內修改全局變量x呢?我們先試試用global(全局)。


運行後報錯,提示語法錯誤。原來global修飾變量時不能直接賦值,修改爲如下:


運行結果:


可以看到main1位置的x和func內部func1位置的x是同一個值,但和func內部的func2以及main2位置的x不一樣了,反而是main2處的x和func內部的x變量是同一個。

第二回合:global關鍵字修飾函數內部變量後標誌其是全局變量(這裏不能說global將x從局部變量改爲了全局變量),如果用global修飾函數內的變量,必須在使用該變量前進行修飾(否則會發生變量未定義的錯誤,請你自己嘗試一下)。

我們試試nonlocal關鍵字呢?


報錯了,無法使用nonlocal關鍵字。

接下來我們看看怎樣使用nonlocal關鍵字。

我們先添加一個嵌套函數:


輸出結果:


可以看到嵌套函數內默認使用的也是全局變量。我們在func函數中修改一下x的值試試。


輸出結果:


可以看到在func函數中修改x後,x被標識成局部變量,它的改變並沒有影響全局變量x,但嵌套函數ifunc中的x受到了影響,顯示ifunc中的x是func函數中的局部變量。

我們再繼續修改一下ifunc中x的值。


輸出結果:


可以看到在ifunc修改x的之後即沒有影響func中的局部變量x,也沒有影響全局變量x,ifunc中的x是函數ifunc自己的局部變量。

第三回合:如果在嵌套函數和函數(這裏指包含嵌套函數的那個函數)中存在和全局變量同名的變量,如果直接使用,而不修改變量的值,那麼這三個位置的變量使用的是同一個全局變量,如果在函數中修改了變量值,那麼該變量會被標識爲該函數的局部變量,嵌套函數直接使用時使用的是該函數的局部變量。如果在嵌套函數中修改同名變量的值,那麼嵌套函數中的該變量會被標識爲該嵌套函數的局部變量,它的修改不影響函數中同名變量和全局變量。

我們在嵌套函數中添加global關鍵字試試。

先不修改ifunc中x的值:


輸出結果:


可以看出嵌套函數ifunc中的x是全局變量。

再修改一下ifunc中x的值試試:


輸出結果:


可以看出嵌套函數中x是全局變量,但它的修改沒有影響到func函數中的同名局部變量。

我們在前邊已經發現在func函數中直接使用nonlocal關鍵字發生了報錯,我們再試試在ifunc中使用nonlocal關鍵字:


輸出結果:


可以看到nonlocal修飾後,ifunc中的x和func中的x是同一個變量,ifunc中修改x的值影響了func中的x(因爲是一個變量),但並沒有影響全局變量x。

再擴展一下:

在func函數中用global修飾x並修改ifunc中x的值,看看有什麼變化:


輸出結果:


我們再用nonlocal修飾一下ifunc函數中的x:


運行時發生報錯,提示沒有爲ifunc中的x找到綁定。

第四回合:global可以在任何地方修飾變量,而且被global修飾的變量直接被標識爲全局變量,對該變量修改會影響全局變量的值,但不影響函數中未被global修飾的同名變量(依然是局部變量),nonlocal只能在嵌套函數(可能還有其他的地方,我還沒有檢查)中使用,用於標識嵌套函數中的變量是包含該嵌套函數的函數中的同名變量,在嵌套函數中修改變量會影響函數中的變量。如果在函數中使用global修飾了變量,那麼在嵌套函數中用nonlocal修飾同名變量會發生報錯,因爲nonlocal表示該變量在函數中已經定義,但檢查時因爲同名變量被global修飾爲全局變量,所以不存在同名的局部變量,從而導致錯誤。

如果文章中的內容存在錯誤,請大家指出來,如果你有更好的建議或意見,還請不吝賜教。謝謝。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章