Python命名空間

分四部分揭示Python命名空間的本質(zhì):

一躏鱼、命名空間的定義

Python使用叫做命名空間的東西來(lái)記錄變量的軌跡蜕窿。命名空間是一個(gè) 字典(dictionary) 谋逻,它的鍵就是變量名,它的值就是那些變量的值桐经。
A namespace is a mapping from names to objects. Most namespaces are currently implemented as Python dictionaries毁兆。

在一個(gè) Python 程序中的任何一個(gè)地方,都存在幾個(gè)可用的命名空間阴挣。
1气堕、每個(gè)函數(shù)都有著自已的命名空間,叫做局部命名空間畔咧,它記錄了函數(shù)的變量茎芭,包括函數(shù)的參數(shù)和局部定義的變量。
2誓沸、每個(gè)模塊擁有它自已的命名空間梅桩,叫做全局命名空間,它記錄了模塊的變量蔽介,包括函數(shù)摘投、類、其它導(dǎo)入的模塊虹蓄、模塊級(jí)的變量和常量犀呼。
3、還有就是內(nèi)置命名空間薇组,任何模塊均可訪問(wèn)它外臂,它存放著內(nèi)置的函數(shù)和異常。

二律胀、命名空間的查找順序

當(dāng)一行代碼要使用變量 x 的值時(shí)宋光,Python 會(huì)到所有可用的名字空間去查找變量,按照如下順序:
1炭菌、局部命名空間:特指當(dāng)前函數(shù)或類的方法罪佳。如果函數(shù)定義了一個(gè)局部變量 x,或一個(gè)參數(shù) x黑低,Python 將使用它赘艳,然后停止搜索酌毡。
2、全局命名空間:特指當(dāng)前的模塊蕾管。如果模塊定義了一個(gè)名為 x 的變量枷踏,函數(shù)或類,Python 將使用它然后停止搜索掰曾。
3旭蠕、內(nèi)置命名空間:對(duì)每個(gè)模塊都是全局的。作為最后的嘗試旷坦,Python 將假設(shè) x 是內(nèi)置函數(shù)或變量掏熬。
4、如果 Python 在這些名字空間找不到 x塞蹭,它將放棄查找并引發(fā)一個(gè) NameError 異常孽江,如,NameError: name 'aa' is not defined番电。

嵌套函數(shù)的情況:
1、先在當(dāng)前 (嵌套的或 lambda) 函數(shù)的命名空間中搜索
2辆琅、然后是在父函數(shù)的命名空間中搜索
3漱办、接著是模塊命名空間中搜索
4、最后在內(nèi)置命名空間中搜索
示例:

info = "Adress : "
def func_father(country):
    def func_son(area):
        city= "Shanghai " #此處的city變量婉烟,覆蓋了父函數(shù)的city變量
        print(info + country + city + area)
    city = " Beijing "
    #調(diào)用內(nèi)部函數(shù)
    func_son("ChaoYang ");
 
func_father("China ")

輸出:Adress : China Shanghai ChaoYang

以上示例中娩井,info在全局命名空間中,country在父函數(shù)的命名空間中似袁,city洞辣、area在自己函數(shù)的命名空間中

三、命名空間的生命周期

不同的命名空間在不同的時(shí)刻創(chuàng)建昙衅,有不同的生存期扬霜。
1、內(nèi)置命名空間在 Python 解釋器啟動(dòng)時(shí)創(chuàng)建而涉,會(huì)一直保留著瓶,不被刪除。
2啼县、模塊的全局命名空間在模塊定義被讀入時(shí)創(chuàng)建材原,通常模塊命名空間也會(huì)一直保存到解釋器退出。
3季眷、當(dāng)函數(shù)被調(diào)用時(shí)創(chuàng)建一個(gè)局部命名空間余蟹,當(dāng)函數(shù)返回結(jié)果 或 拋出異常時(shí),被刪除子刮。每一個(gè)遞歸調(diào)用的函數(shù)都擁有自己的命名空間威酒。

Python 的一個(gè)特別之處在于其賦值操作總是在最里層的作用域。賦值不會(huì)復(fù)制數(shù)據(jù)——只是將命名綁定到對(duì)象。刪除也是如此:"del y" 只是從局部作用域的命名空間中刪除命名 y 兼搏。事實(shí)上卵慰,所有引入新命名的操作都作用于局部作用域。

i=1
def func2():
    i=i+1
 
func2();
#錯(cuò)誤:UnboundLocalError: local variable 'i' referenced before assignment

由于創(chuàng)建命名空間時(shí)佛呻,python會(huì)檢查代碼并填充局部命名空間裳朋。在python運(yùn)行那行代碼之前,就發(fā)現(xiàn)了對(duì)i的賦值吓著,并把它添加到局部命名空間中鲤嫡。當(dāng)函數(shù)執(zhí)行時(shí),python解釋器認(rèn)為i在局部命名空間中但沒(méi)有值绑莺,所以會(huì)產(chǎn)生錯(cuò)誤暖眼。

def func3():
  y=123
  del y
  print(y)

func3()
#錯(cuò)誤:UnboundLocalError: local variable 'y' referenced before assignment
#去掉"del y"語(yǔ)句后,運(yùn)行正常

四纺裁、通過(guò)locals()和globals() BIF訪問(wèn)命名空間

1诫肠、局部命名空間可以 locals() BIF來(lái)訪問(wèn)。

locals 返回一個(gè)名字/值對(duì)的 dictionary欺缘。這個(gè) dictionary 的鍵是字符串形式的變量名字栋豫,dictionary 的值是變量的實(shí)際值。
示例:

def func1(i, str ):
    x = 12345
    print(locals())
 
func1(1 , "first")

輸出:{'str': 'first', 'x': 12345, 'i': 1}
2谚殊、全局 (模塊級(jí)別)命名空間可以通過(guò) globals() BIF來(lái)訪問(wèn)丧鸯。
示例:

'''Created on 2013-5-26'''
 
import copy
from copy import deepcopy
 
gstr = "global string"
 
def func1(i, info):
    x = 12345
    print(locals())
 
func1(1 , "first")
 
if __name__ == "__main__":
    print("the current scope's global variables:")
    dictionary=globals()
    print(dictionary)

輸出:
{
'name': 'main',
'doc': 'Created on 2013-5-26',
'package': None,
'cached': None,
'file': 'E:\WorkspaceP\Test1\src\base\test1.py',
'loader': <_frozen_importlib.SourceFileLoader object at 0x01C702D0>,
'copy': <module 'copy' from 'D:\Python33\lib\copy.py'>,
'builtins': <module 'builtins' (built-in)>,
'gstr': 'global string',
'dictionary': {...},
'func1': <function func1 at 0x01C6C540>,
'deepcopy': <function deepcopy at 0x01DB28A0>
}

  • 總結(jié)
      1、模塊的名字空間不僅僅包含模塊級(jí)的變量和常量嫩絮,還包括所有在模塊中定義的函數(shù)和類丛肢。除此以外,它還包括了任何被導(dǎo)入到模塊中的東西剿干。
      2蜂怎、我們看到,內(nèi)置命名也同樣被包含在一個(gè)模塊中怨愤,它被稱作 builtin派敷。
      3、回想一下 from module import 和 import module 之間的不同撰洗。
        使用 import module篮愉,模塊自身被導(dǎo)入,但是它保持著自已的名字空間差导,這就是為什么您需要使用模塊名來(lái)訪問(wèn)它的函數(shù)或?qū)傩裕簃odule.function 的原因试躏。
        但是使用 from module import function,實(shí)際上是從另一個(gè)模塊中將指定的函數(shù)和屬性導(dǎo)入到您自己的名字空間设褐,這就是為什么您可以直接訪問(wèn)它們卻不需要引用它們所來(lái)源的模塊颠蕴。使用 globals 函數(shù)泣刹,您會(huì)真切地看到這一切的發(fā)生,見(jiàn)上面的紅色輸出語(yǔ)句犀被。

3椅您、 locals 與 globals 之間的一個(gè)重要的區(qū)別

locals 是只讀的,globals 不是

def func1(i, info):
    x = 12345
    print(locals())
    locals()["x"]= 6789
    print("x=",x)
 
y=54321
func1(1 , "first")
globals()["y"]= 9876
print( "y=",y)

輸出:
{'i': 1, 'x': 12345, 'info': 'first'}
x= 12345
y= 9876
解釋:
  locals 實(shí)際上沒(méi)有返回局部名字空間寡键,它返回的是一個(gè)拷貝掀泳。所以對(duì)它進(jìn)行改變對(duì)局部名字空間中的變量值并無(wú)影響。
  globals 返回實(shí)際的全局名字空間西轩,而不是一個(gè)拷貝员舵。所以對(duì) globals 所返回的 dictionary 的任何的改動(dòng)都會(huì)直接影響到全局變量。

Ref:http://www.cnblogs.com/windlaughing/archive/2013/05/26/3100362.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末藕畔,一起剝皮案震驚了整個(gè)濱河市马僻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌注服,老刑警劉巖韭邓,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異溶弟,居然都是意外死亡仍秤,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門可很,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人凰浮,你說(shuō)我怎么就攤上這事我抠。” “怎么了袜茧?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵菜拓,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我笛厦,道長(zhǎng)纳鼎,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任裳凸,我火速辦了婚禮贱鄙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘姨谷。我一直安慰自己逗宁,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布梦湘。 她就那樣靜靜地躺著瞎颗,像睡著了一般件甥。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上哼拔,一...
    開(kāi)封第一講書(shū)人閱讀 51,190評(píng)論 1 299
  • 那天引有,我揣著相機(jī)與錄音,去河邊找鬼倦逐。 笑死譬正,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的僻孝。 我是一名探鬼主播导帝,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼穿铆!你這毒婦竟也來(lái)了您单?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤荞雏,失蹤者是張志新(化名)和其女友劉穎虐秦,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體凤优,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡悦陋,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了筑辨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片俺驶。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖棍辕,靈堂內(nèi)的尸體忽然破棺而出暮现,到底是詐尸還是另有隱情,我是刑警寧澤楚昭,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布栖袋,位于F島的核電站,受9級(jí)特大地震影響抚太,放射性物質(zhì)發(fā)生泄漏塘幅。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一尿贫、第九天 我趴在偏房一處隱蔽的房頂上張望电媳。 院中可真熱鬧,春花似錦帅霜、人聲如沸匆背。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)钝尸。三九已至括享,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間珍促,已是汗流浹背铃辖。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留猪叙,地道東北人娇斩。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像穴翩,于是被迫代替她去往敵國(guó)和親犬第。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 變量是擁有匹配對(duì)象的名字(標(biāo)識(shí)符)芒帕。命名空間是一個(gè)包含了變量名稱們(鍵)和它們各自相應(yīng)的對(duì)象們(值)的字典歉嗓。一個(gè)P...
    DraculaWong閱讀 861評(píng)論 0 0
  • 前言 前段時(shí)間寫(xiě)腳本的時(shí)候,在調(diào)用函數(shù)的時(shí)候背蟆,一直在想在python中函數(shù)的參數(shù)是傳值還是傳引用鉴分?先看一下下面兩個(gè)...
    Allenware閱讀 5,216評(píng)論 0 11
  • 問(wèn)題 之前一個(gè)同學(xué)寫(xiě) python 時(shí)遇到了一個(gè)錯(cuò)誤,我看了 python 的報(bào)錯(cuò)提示带膀,如下: UnboundLo...
    除囧閱讀 312評(píng)論 0 0
  • 好好學(xué)習(xí)志珍,天天向上,今天是:2017.05.19 Python命名空間垛叨、作用域一直沒(méi)看懂伦糯。這篇文是網(wǎng)上看到的,寫(xiě)的...
    Wakingup88688閱讀 1,376評(píng)論 4 1
  • 個(gè)人筆記嗽元,方便自己查閱使用 Py.LangSpec.Contents Refs Built-in Closure ...
    freenik閱讀 67,696評(píng)論 0 5