1. 程式人生 > >Python中關鍵字global與nonlocal的區別

Python中關鍵字global與nonlocal的區別

版權宣告:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/xCyansun/article/details/79672634
終於下定決心學習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修飾為全域性變數,所以不存在同名的區域性變數,從而導致錯誤。

如果文章中的內容存在錯誤,請大家指出來,如果你有更好的建議或意見,還請不吝賜教。謝謝。
---------------------
作者:雁丘1990
來源:CSDN
原文:https://blog.csdn.net/xcyansun/article/details/79672634
版權宣告:本文為博主原創文章,轉載請附上博文連結!