Python函數(shù)中的作用域規(guī)則詳解
Python是靜態(tài)作用域語言,但是它自身是一個(gè)動(dòng)態(tài)語言。在Python中變量的作用域是由變量在代碼中的位置決定的,與C語言有些相似,但不是完全一樣。
在Python 2.0及之前的版本中,Python只支持3種作用域,即局部作用域,全局作用域,內(nèi)置作用域;在Python
2.2中,Python正式引入了一種新的作用域 — 嵌套作用域;嵌套作用域的引入,本質(zhì)上為Python實(shí)現(xiàn)了對閉包的支持。
1、簡單介紹一下閉包
def test(): A = 3 B = 4 def stu(): C = 3 return A+B+C return stu stu = test() stu
在上述此代碼中stu方法定義在test的內(nèi)部,內(nèi)部函數(shù)stu即可以使用外部函數(shù)test的變量,我們稱這種行為叫做閉包。
2、在Python中,并不是任何代碼塊都能引入新的作用域
Python中不是任何代碼塊都可以引入新的作用域這與C有很大的不同:
在C中:
#include<stdio.h>
int main() {
if(2 > 0) {
int i = 0;
}
printf("i = %d", i);
return 0;
}
在上述代碼中,if子句引入了一個(gè)局部作用域,變量i就存在于這個(gè)局部作用域中,但對外不可見,因此,接下來在printf函數(shù)中對變量i的引用會(huì)引發(fā)編譯錯(cuò)誤。
但是,在Python中卻并非如此:
if True:
i = 0
print i
在上述代碼中,if子句并沒有引入一個(gè)局部作用域,變量i仍然處在全局作用域中,因此,變量i對于接下來的print語句是可見的。
實(shí)際上,在Python中,只有模塊,類以及函數(shù)才會(huì)引入新的作用域,其它的代碼塊是不會(huì)引入新的作用域的。
在Python中,使用一個(gè)變量之前不必預(yù)先聲明它,但是在真正使用它之前,它必須已經(jīng)綁定到某個(gè)對象;而名字綁定將在當(dāng)前作用域中引入新的變量,同時(shí)屏蔽外層作用域中的同名變量,不論這個(gè)名字綁定發(fā)生在當(dāng)前作用域中的哪個(gè)位置。
>>> f() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in f NameError: name 'i' is not defined >>>
運(yùn)行結(jié)果報(bào)錯(cuò):
NameError: name ‘i’ is not defined
程序運(yùn)行時(shí),Python首先在函數(shù)f的本地作用域中查找變量i,查找失敗,接著在全局作用域和內(nèi)置作用域中查找變量i,仍然失敗,最終拋出NameError異常。
>>> def f(): ... i = 8 ... print(i) ... >>> f() 8 >>> print(i) 0 >>>
運(yùn)行結(jié)果顯示:
8和0
i = 8是一個(gè)名字綁定操作,它在函數(shù)f的局部作用域中引入了新的變量i,屏蔽了全局變量i,因此f內(nèi)部的print語句看到的是局部變量i,f外部的print語句看到的是全局變量i。
>>> i = 0 >>> def f(): ... print(i) ... i = 0 ... >>> f() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in f UnboundLocalError: local variable 'i' referenced before assignment >>>
運(yùn)行結(jié)果報(bào)錯(cuò):
UnboundLocalError: local variable ‘i’ referenced before assignment
在上述中,函數(shù)f中的變量i是局部變量,但是在print語句使用它的時(shí)候,它還未被綁定到任何對象之上,所以拋出異常。
3、在Python中,名字綁定在所屬作用域中引入新的變量,同時(shí)綁定到一個(gè)對象。
名字綁定發(fā)生在以下幾種情況之下:
- 參數(shù)聲明:參數(shù)聲明在函數(shù)的局部作用域中引入新的變量;
- 賦值操作:對一個(gè)變量進(jìn)行初次賦值會(huì)在當(dāng)前作用域中引入新的變量,后續(xù)賦值操作則會(huì)重新綁定該變量;
- 類和函數(shù)定義:類和函數(shù)定義將類名和函數(shù)名作為變量引入當(dāng)前作用域,類體和函數(shù)體將形成另外一個(gè)作用域;
- import語句:import語句在當(dāng)前作用域中引入新的變量,一般是在全局作用域;
- for語句:for語句在當(dāng)前作用域中引入新的變量(循環(huán)變量);
- except語句:except語句在當(dāng)前作用域中引入新的變量(異常對象);
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
淺談配置MMCV環(huán)境,解決報(bào)錯(cuò),版本不匹配問題
這篇文章主要介紹了淺談配置MMCV環(huán)境,解決報(bào)錯(cuò),版本不匹配問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-04-04
conda換源安裝torch+vscode分布式訓(xùn)練調(diào)試的實(shí)現(xiàn)
本文主要介紹了conda換源安裝torch+vscode分布式訓(xùn)練調(diào)試的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-06-06
實(shí)踐Python的爬蟲框架Scrapy來抓取豆瓣電影TOP250
這篇文章主要介紹了實(shí)踐Python的爬蟲框架Scrapy來抓取豆瓣電影TOP250的過程,文中的環(huán)境基于Windows操作系統(tǒng),需要的朋友可以參考下2016-01-01
Python讀取和處理文件后綴為.sqlite的數(shù)據(jù)文件(實(shí)例講解)
下面小編就為大家?guī)硪黄狿ython讀取和處理文件后綴為.sqlite的數(shù)據(jù)文件(實(shí)例講解)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-06-06
vue.js實(shí)現(xiàn)輸入框輸入值內(nèi)容實(shí)時(shí)響應(yīng)變化示例
這篇文章主要介紹了vue.js實(shí)現(xiàn)輸入框輸入值內(nèi)容實(shí)時(shí)響應(yīng)變化,結(jié)合實(shí)例形式分析了vue.js使用v-model屬性進(jìn)行數(shù)據(jù)綁定的相關(guān)操作技巧,需要的朋友可以參考下2018-07-07

