Python中的範圍規則詳解

來源:互聯網
上載者:User
Python是靜態範圍語言,儘管它自身是一個動態語言。也就是說,在Python中變數的範圍是由它在原始碼中的位置決定的,這與C有些相似,但是Python與C在範圍方面的差異還是非常明顯的。

接下來會談論Python的範圍規則,在這中間也會說明一下Python與C在範圍方面的不同。

在Python 2.0及之前的版本中,Python只支援3種範圍,即局部範圍,全域範圍,內建範圍;在Python 2.2中,Python正式引入了一種新的範圍 --- 嵌套範圍;在Python 2.1中,嵌套範圍可以作為一個選項被開啟;嵌套範圍的引入,本質上為Python實現了對閉包的支援,關於閉包的知識,網上有很多解釋,這裡就不詳細展開了。相應地,變數尋找順序由之前的LGB變成LEGB(L:Local,E:Enclosing,G:Global,B:Built-in)。

在Python中,並不是任何代碼塊都能引入新的範圍,這與C有很大的不同:

代碼如下:


#include
int main() {
if(2 > 0) {
int i = 0;
}
printf("i = %d", i);
return 0;
}

在這段代碼中,if子句引入了一個局部範圍,變數i就存在於這個局部範圍中,但對外不可見,因此,接下來在printf函數中對變數i的引用會引發編譯錯誤。

但是,在Python中卻並非如此:

代碼如下:


if True:
i = 0
print i

在這段代碼中,if子句並沒有引入一個局部範圍,變數i仍然處在全域範圍中,因此,變數i對於接下來的print語句是可見的。

實際上,在Python中,只有模組,類以及函數才會引入新的範圍,其它的代碼塊是不會引入新的範圍的。

在Python中,使用一個變數之前不必預先聲明它,但是在真正使用它之前,它必須已經綁定到某個對象;而名字綁定將在當前範圍中引入新的變數,同時屏蔽外層範圍中的同名變數,不論這個名字綁定發生在當前範圍中的哪個位置。

代碼如下:


def f():
print i
f()

運行結果將顯示:NameError: global name 'i' is not defined。Python首先在函數f的本地範圍中尋找變數i,尋找失敗,接著在全域範圍和內建範圍中尋找變數i,仍然失敗,最終拋出NameError異常。

代碼如下:


i = 0
def f():
i = 8
print i
f()
print i

運行結果顯示:8和0。i = 8是一個名字綁定操作,它在函數f的局部範圍中引入了新的變數i,屏蔽了全域變數i,因此f內部的print語句看到的是局部變數i,f外部的print語句看到的是全域變數i。

代碼如下:


i = 0
def f():
print i
i = 0
f()

運行結果顯示:UnboundLocalError: local variable 'i' referenced before assignment。在這個例子當中,函數f中的變數i是局部變數,但是在print語句使用它的時候,它還未被綁定到任何對象之上,所以拋出異常。

代碼如下:


print i
i = 0


不論是以互動的方式運行,還是以指令檔的方式運行,結果都顯示:NameError: name 'i' is not defined。這裡的輸出結果又與上一個例子不同,這是因為它在頂級範圍(模組範圍)的緣故。對於模組代碼而言,代碼在執行之前,沒有經過什麼預先處理,但是對於函數體而言,代碼在運行之前已經經過了一個預先處理,因此不論名字綁定發生在範圍的那個位置,它都能感知出來。Python雖然是一個靜態範圍語言,但是名字尋找確實動態發生的,因此直到啟動並執行時候,才會發現名字方面的問題。

在Python中,名字綁定在所屬範圍中引入新的變數,同時綁定到一個對象。名字綁定發生在以下幾種情況之下:

1.參數聲明:參數聲明在函數的局部範圍中引入新的變數;
2.賦值操作:對一個變數進行初次賦值會在當前範圍中引入新的變數,後續賦值操作則會重新綁定該變數;
3.類和函數定義:類和函數定義將類名和函數名作為變數引入當前範圍,類體和函數體將形成另外一個範圍;
4.import語句:import語句在當前範圍中引入新的變數,一般是在全域範圍;
5.for語句:for語句在當前範圍中引入新的變數(迴圈變數);
6.except語句:except語句在當前範圍中引入新的變數(異常對象)。

在Python中,類定義所引入的範圍對於成員函數是不可見的,這與C++或者Java是很不同的,因此在Python中,成員函數想要引用類體定義的變數,必須通過self或者類名來引用它。

嵌套範圍的加入,會導致一些代碼編譯不過或者得到不同的運行結果,在這裡Python解譯器會協助你識別這些可能引起問題的地方,給出警告。

locals函數返回所有的局部變數,但是不會返回嵌套範圍中的變數,實際上沒有函數會返回嵌套範圍中的變數。

  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.