摘要:理解的名字空間的名字空間是一個(gè)非常核心的內(nèi)容。在中提供了一個(gè)關(guān)鍵字來(lái)修改外部嵌套函數(shù)的名字空間,但是要使用才有,我等使用的只能眼饞一下。
理解 Python 的 LEGB 名字空間
Python 的名字空間是 Python 一個(gè)非常核心的內(nèi)容。
其他語(yǔ)言中如 C 中,變量名是內(nèi)存地址的別名,而在 Python 中,名字是一個(gè)字符串對(duì)象,它與他指向的對(duì)象構(gòu)成一個(gè){name:object}關(guān)聯(lián)。
Python 由很多名字空間,而 LEGB 則是名字空間的一種查找規(guī)則。
Python 中name-object的關(guān)聯(lián)存儲(chǔ)在不同的作用域中,各個(gè)不同的作用域是相互獨(dú)立的。而我們就在不同的作用域中搜索name-object。
舉個(gè)栗子,來(lái)說(shuō)明作用域是相互獨(dú)立的。
In [11]: i = "G" In [12]: def test(): i = "L" print i, "in locals" ....: In [13]: test() L in locals In [14]: print i, "in globals" G in globals
在上面的栗子中,我們定義了兩次 i,在 test 函數(shù)中是 i-L,在外面是 i-G。為什么在 test 函數(shù)中,我們 i 指向的是對(duì)象 L,而在外面,i 指向的則是 G?這就是 LEGB 的作用。
簡(jiǎn)述簡(jiǎn)而言之,LEGB 代表名字查找順序: 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ò)于{{BANNED}},不推薦這么做。
locals,globals函數(shù)的形參跟內(nèi)部變量都存儲(chǔ)在 locals 中。
In [1]: def f(x): ...: a = x ...: print a ...: print locals() ...: In [2]: f("hello") hello {"a": "hello", "x": "hello"}
不過(guò)在函數(shù)內(nèi)部調(diào)用global 聲明的時(shí)候,可以將變量存儲(chǔ)在 globals 中
In [6]: def f(x): ...: global a ...: a = x ...: print a ...: print locals() ...: In [7]: f("hello") hello {"x": "hello"} In [8]: print a hello In [9]: print x --------------------------------------------------------------------------- NameError Traceback (most recent call last)in () ----> 1 print x NameError: name "x" is not defined
如上面栗子中那樣,在函數(shù)中聲明 a 為全局變量,則函數(shù) f 的 locals只有參數(shù) x,而沒(méi)有變量,而在外部可以使用變量 a,而使用 x 的時(shí)候則是NameError
EnclosedEnclosing 是外部嵌套函數(shù)的名字空間。我們經(jīng)常在閉包中用到。在 Python3中提供了一個(gè) nonlocal關(guān)鍵字來(lái)修改外部嵌套函數(shù)的名字空間,但是要使用 Python3才有,我等使用 Python2的只能眼饞一下。
In [11]: def outer(): ....: a_var = "enclosed value" ....: print a_var ....: def inner(): ....: a_var = "local value" ....: print(a_var) ....: inner() ....: print a_var ....: In [12]: outer() enclosed value local value enclosed value
下面的栗子簡(jiǎn)單示范一下 nonlocal 的用法,實(shí)在 Python3下面才可以正常運(yùn)行的:
In [1]: a_var = "global value" In [2]: def outer(): ...: a_var = "local value" ...: print("outer befor", a_var) ...: def inner(): ...: nonlocal a_var ...: a_var = "inner value" ...: print("in inner():", a_var) ...: inner() ...: print("outer inner:", a_var) ...: In [3]: outer() outer befor local value in inner(): inner value outer inner: inner value In [4]: print(a_var) global valuebuiltins
builtins 則是內(nèi)置模塊,輕易不要修改
In [19]: b --------------------------------------------------------------------------- NameError Traceback (most recent call last)in () ----> 1 b NameError: name "b" is not defined In [20]: __builtins__.b = "builtins" In [21]: b Out[21]: "builtins"
上面栗子中在第一次調(diào)用b的時(shí)候報(bào)錯(cuò)NameError,之后我們修改 builtins 的名字空間,將名字b與值"builtins"進(jìn)行關(guān)聯(lián),就可以正常調(diào)用了。這種非常規(guī)用法不建議使用。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/37330.html
摘要:例題核心編程第二版變量作用域和命名空間一節(jié)有以下一道題目請(qǐng)問(wèn)輸出結(jié)果是什么要想解這道題,必須先了解中的一些概念的變量名解析機(jī)制有時(shí)稱為。 例題 《核心編程(第二版)》變量作用域和命名空間一節(jié)有以下一道題目 # coding=utf-8 #!/usr/bin/env python def proc1(): j,k = 3,4 print j == %d and k ==...
摘要:約束名字空間作用域之間的那些事不管在什么編程語(yǔ)言都有作用域這個(gè)概念作用域控制在它范圍內(nèi)代碼的生存周期包括名字和實(shí)體的綁定名字和實(shí)體的綁定我們可以理解成賦值當(dāng)我們執(zhí)行這句代碼時(shí)實(shí)際上我們已經(jīng)得到一個(gè)的關(guān)聯(lián)關(guān)系我們也能將稱之為約束這個(gè)約束也將存 約束 名字空間 作用域 之間的那些事 不管在什么編程語(yǔ)言, 都有作用域這個(gè)概念.作用域控制在它范圍內(nèi)代碼的生存周期, 包括名字和實(shí)體的綁定. 名字...
摘要:真正管理這些名子的事物就是本文的主角命名空間。閉包命名空間閉包函數(shù)的名稱空間引入。函數(shù)調(diào)用時(shí)產(chǎn)生新的局部命名空間函數(shù)返回結(jié)果拋出異常時(shí)釋放命名空間,每一次遞歸都生成一個(gè)命名空間。標(biāo)識(shí)符產(chǎn)生地點(diǎn)決定標(biāo)識(shí)符所處的命名空間。 懶得掃全文的童鞋,可以直接跳到最后看總結(jié)。我們先從一個(gè)簡(jiǎn)單的栗子說(shuō)起: 栗子 a 文件中有變量 va 以及類 A,b 文件導(dǎo)入 a 中class A ,并打印出 A: ...
摘要:當(dāng)程序引用某個(gè)變量的名字時(shí),就會(huì)從當(dāng)前名字空間開(kāi)始搜索。對(duì)于可以看出已經(jīng)被導(dǎo)入到自己的名字空間了,而不是在里面。因此并沒(méi)有涉及到修改名字空間。按照原則,搜到有變量并且是個(gè)然后將其加入到自己的后面的就開(kāi)始讀取的元素,并沒(méi)有影響的名字空間。 源自我的博客 前言 python里面最核心的內(nèi)容就是:名字空間(namespace) 例子引入 例1 #!/usr/bin/env python #...
摘要:在函數(shù)中執(zhí)行賦值操作時(shí),會(huì)創(chuàng)建一個(gè)局部變量,如果想在函數(shù)中通過(guò)賦值改變一個(gè)全局變量,則需要用關(guān)鍵字申明,只要出現(xiàn)了操作符,則這個(gè)變量就是局部變量,除非顯示申明為。 python變量與變量作用域 c語(yǔ)言中,變量的定義會(huì)為變量分配一塊內(nèi)存,變量的內(nèi)存地址不會(huì)發(fā)生改變,當(dāng)變量的值發(fā)生改變時(shí),改變的是對(duì)應(yīng)內(nèi)存地址中的值。 python中,給變量賦值時(shí),變量保存的是一個(gè)對(duì)象的引用,如果想改變變...
閱讀 1409·2021-09-28 09:43
閱讀 4281·2021-09-04 16:41
閱讀 1946·2019-08-30 15:44
閱讀 3792·2019-08-30 15:43
閱讀 804·2019-08-30 14:21
閱讀 2058·2019-08-30 11:00
閱讀 3350·2019-08-29 16:20
閱讀 1949·2019-08-29 14:21