摘要:理解的名字空間的名字空間是一個非常核心的內容。在中提供了一個關鍵字來修改外部嵌套函數的名字空間,但是要使用才有,我等使用的只能眼饞一下。
理解 Python 的 LEGB 名字空間
Python 的名字空間是 Python 一個非常核心的內容。
其他語言中如 C 中,變量名是內存地址的別名,而在 Python 中,名字是一個字符串對象,它與他指向的對象構成一個{name:object}關聯。
Python 由很多名字空間,而 LEGB 則是名字空間的一種查找規則。
Python 中name-object的關聯存儲在不同的作用域中,各個不同的作用域是相互獨立的。而我們就在不同的作用域中搜索name-object。
舉個栗子,來說明作用域是相互獨立的。
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 函數中是 i-L,在外面是 i-G。為什么在 test 函數中,我們 i 指向的是對象 L,而在外面,i 指向的則是 G?這就是 LEGB 的作用。
簡述簡而言之,LEGB 代表名字查找順序: locals -> enclosing function -> globals -> __builtins__
locals 是函數內的名字空間,包括局部變量和形參
enclosing 外部嵌套函數的名字空間(閉包中常見)
globals 全局變量,函數定義所在模塊的名字空間
builtins 內置模塊的名字空間
所以,在 Python 中檢索一個變量的時候,優先回到 locals 里面來檢索,檢索不到的情況下會檢索 enclosing ,enclosing 沒有則到 globals 全局變量里面檢索,最后是到 builtins 里面來檢索。
當然,因為 builtins 的特殊性,我們可以直接在 builtins 里面添加變量,這樣就可以在任意模塊中訪問變量,不過這種方法太過于{{BANNED}},不推薦這么做。
locals,globals函數的形參跟內部變量都存儲在 locals 中。
In [1]: def f(x): ...: a = x ...: print a ...: print locals() ...: In [2]: f("hello") hello {"a": "hello", "x": "hello"}
不過在函數內部調用global 聲明的時候,可以將變量存儲在 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
如上面栗子中那樣,在函數中聲明 a 為全局變量,則函數 f 的 locals只有參數 x,而沒有變量,而在外部可以使用變量 a,而使用 x 的時候則是NameError
EnclosedEnclosing 是外部嵌套函數的名字空間。我們經常在閉包中用到。在 Python3中提供了一個 nonlocal關鍵字來修改外部嵌套函數的名字空間,但是要使用 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
下面的栗子簡單示范一下 nonlocal 的用法,實在 Python3下面才可以正常運行的:
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 則是內置模塊,輕易不要修改
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"
上面栗子中在第一次調用b的時候報錯NameError,之后我們修改 builtins 的名字空間,將名字b與值"builtins"進行關聯,就可以正常調用了。這種非常規用法不建議使用。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/37330.html
摘要:例題核心編程第二版變量作用域和命名空間一節有以下一道題目請問輸出結果是什么要想解這道題,必須先了解中的一些概念的變量名解析機制有時稱為。 例題 《核心編程(第二版)》變量作用域和命名空間一節有以下一道題目 # coding=utf-8 #!/usr/bin/env python def proc1(): j,k = 3,4 print j == %d and k ==...
摘要:約束名字空間作用域之間的那些事不管在什么編程語言都有作用域這個概念作用域控制在它范圍內代碼的生存周期包括名字和實體的綁定名字和實體的綁定我們可以理解成賦值當我們執行這句代碼時實際上我們已經得到一個的關聯關系我們也能將稱之為約束這個約束也將存 約束 名字空間 作用域 之間的那些事 不管在什么編程語言, 都有作用域這個概念.作用域控制在它范圍內代碼的生存周期, 包括名字和實體的綁定. 名字...
摘要:真正管理這些名子的事物就是本文的主角命名空間。閉包命名空間閉包函數的名稱空間引入。函數調用時產生新的局部命名空間函數返回結果拋出異常時釋放命名空間,每一次遞歸都生成一個命名空間。標識符產生地點決定標識符所處的命名空間。 懶得掃全文的童鞋,可以直接跳到最后看總結。我們先從一個簡單的栗子說起: 栗子 a 文件中有變量 va 以及類 A,b 文件導入 a 中class A ,并打印出 A: ...
摘要:當程序引用某個變量的名字時,就會從當前名字空間開始搜索。對于可以看出已經被導入到自己的名字空間了,而不是在里面。因此并沒有涉及到修改名字空間。按照原則,搜到有變量并且是個然后將其加入到自己的后面的就開始讀取的元素,并沒有影響的名字空間。 源自我的博客 前言 python里面最核心的內容就是:名字空間(namespace) 例子引入 例1 #!/usr/bin/env python #...
摘要:在函數中執行賦值操作時,會創建一個局部變量,如果想在函數中通過賦值改變一個全局變量,則需要用關鍵字申明,只要出現了操作符,則這個變量就是局部變量,除非顯示申明為。 python變量與變量作用域 c語言中,變量的定義會為變量分配一塊內存,變量的內存地址不會發生改變,當變量的值發生改變時,改變的是對應內存地址中的值。 python中,給變量賦值時,變量保存的是一個對象的引用,如果想改變變...
閱讀 1349·2021-09-28 09:43
閱讀 4116·2021-09-04 16:41
閱讀 1918·2019-08-30 15:44
閱讀 3729·2019-08-30 15:43
閱讀 776·2019-08-30 14:21
閱讀 2037·2019-08-30 11:00
閱讀 3320·2019-08-29 16:20
閱讀 1923·2019-08-29 14:21