python 作用域 前缀_Python 之作用域和名字空间
作用域與名字空間
Python有一個(gè)核心概念是名字空間(namespace),namespace是一個(gè)name到object 的映射關(guān)系,Python有很多namespace,因此,在代碼中如果碰到一個(gè)標(biāo)志符(name),需要有一個(gè)規(guī)則來(lái)決定去哪個(gè)namespace查找——這就是LEGB。
LEGB決定了name的查找順序:locals -> enclosing function -> globals -> __builtins__
locals 是函數(shù)內(nèi)的名字空間,包括局部變量和形參;
enclosing 外部嵌套函數(shù)的名字空間(閉包中常見(jiàn));
globals 全局變量,函數(shù)定義所在模塊的名字空間;
builtins 內(nèi)置模塊的名字空間;
所以,在 Python 中檢索一個(gè)變量的時(shí)候,優(yōu)先到 locals 里面來(lái)檢索,檢索不到的情況下會(huì)檢索 enclosing ,enclosing 沒(méi)有則到 globals 全局變量里面檢索,最后是到 builtins 里面來(lái)檢索。
當(dāng)然,因?yàn)?builtins 的特殊性,我們可以直接在 builtins 里面添加變量,這樣就可以在任意模塊中訪問(wèn)變量,不過(guò)這種方法太過(guò)于變態(tài),不推薦這么做。
LGB規(guī)則(閉包是一種特殊的作用域,暫不考慮)與name space加載的順序相反,Python解釋器初始化的時(shí)候會(huì)先加載built-in namespace,它由__builtins__模塊的名字構(gòu)成,隨后加載global namespace。 如果在執(zhí)行期間調(diào)用了一個(gè)函數(shù),那么將創(chuàng)建局部名字空間。
Python中一切都是object,包括function、module、class、package,這些objects都有在內(nèi)存中真真正正的存在。每個(gè)object都有自己的namespace,每個(gè)object的namespace是獨(dú)立的,可以通過(guò)object.name的方式訪問(wèn)object的namespace中的name,因此,不同的namespace中可以使用相同的name,而不會(huì)引發(fā)混淆。namespace是動(dòng)態(tài)創(chuàng)建的,每一個(gè)namespace的生存時(shí)間也不一樣。例如,一個(gè)module的namespace是它被import的時(shí)候創(chuàng)建的。而function被調(diào)用時(shí),創(chuàng)建其local namespace,調(diào)用結(jié)束或拋出exception的時(shí)候, 該local namespace將被刪除。
locals( )和globals( )分別返回dictionary結(jié)構(gòu)的global namespace和local namespace,例如:
a = 3
defproc():
a= 3
print(locals())print(globals())
proc()
可以看見(jiàn),局部作用域和全局作用域都有變量a,但它們不是同一個(gè)對(duì)象。
注意:還有一個(gè)特殊的module,一進(jìn)入python解釋器,就建立了一個(gè)module,這個(gè)module的namespace就是global namespace,一個(gè)全局唯一的namespace。這個(gè)module的一個(gè)內(nèi)部的attribute,__name__等于__main__。如果模塊是被導(dǎo)入的,__name__的值為模塊的名字;如果模塊是被直接執(zhí)行的,__name__的值為’__main__’。
scope(作用域):用unqualified reference name(即與object.name相比,沒(méi)有object的前綴)就可以直接找到name所指的對(duì)象。 LGB規(guī)則用scope的概念來(lái)解釋就是:在任何代碼執(zhí)行的時(shí)候,都至少有3個(gè)scope,從內(nèi)到外一次查找一個(gè)unqualified reference name。
函數(shù)體內(nèi)的局部變量和全局變量如果重名,全局變量不可見(jiàn)(被局部變量覆蓋)。
x = 50
deffunc(x):print('x=', x) #50
x = 2
print('x=', x) #2
func(x)print('x=', x) #50
一個(gè)更復(fù)雜的例子:
j, k = 1, 2
defproc1():
j, k= 3, 4
print "j==%d and k=%d" %(j,k)
k= 5
defproc2():
j= 6proc1()print "j==%d and k=%d" %(j,k)
k= 7proc1()print "j==%d and k=%d" %(j,k)
j= 8proc2()print "j==%d and k=%d" %(j,k)
當(dāng)在函數(shù)中需要修改全局變量時(shí),如果沒(méi)有g(shù)lobal關(guān)鍵字則會(huì)出錯(cuò):
x = 50
defrun():printx
x= 2run()
報(bào)錯(cuò)為:UnboundLocalError: local variable 'x' referenced before assignment
加上global關(guān)鍵字以后則OK
x = 50
defrun():globalx
x= 2run()print x #2
總結(jié)
以上是生活随笔為你收集整理的python 作用域 前缀_Python 之作用域和名字空间的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 如何让控件span的id调用ajax_微
- 下一篇: python httpstr find_