python 命令空間和作用域

一、命令空間

    1. 命名空間是名字和對象的映射.可以把一個namespace理解為一個字典.大部分namespace都是按Python中的字典來實現(xiàn)的.
      各個命名空間是獨立的,沒有任何關系的,所以同一個命名空間中不能有重名,但不同的命名空間是可以重名而沒有任何影響.

      順便提一句,我稱Python 中任何一個“.”之后的命名為屬性--例如,表達式z.real 中的real 是對象z 的一個屬性.
      嚴格來講,從模塊中引用命名是引用屬性:表達式modname.funcname 中, modname 是一個模塊對象,funcname 是它的一個屬性.
      在這種情況下,模塊的屬性和模塊中定義的全局名稱之間會有一個簡單的映射:它們共享相同的名稱空間.

    1. 那么哪些可以是一個namespace呢?
      Python的 built-in names(包括內置函數(shù),內置常量,內置類型);
      一個模塊的global names(這個模塊定義的函數(shù),類,變量);
      一個函數(shù)的所有l(wèi)ocal names ;
      從某種意義上說,對象的屬性集也構成了一個名稱空間;
    1. 命名空間都是有創(chuàng)建時間和生存期的.
      對于Python built-in names組成的命名空間,它在Python解釋器啟動的時候被創(chuàng)建,在解釋器退出的時候才被刪除;
      對于一個Python模塊的global namespace,它在這個module被import的時候創(chuàng)建,在解釋器退出的時候退出;
      對于一個函數(shù)的local namespace,它在函數(shù)每次被調用的時候創(chuàng)建,函數(shù)返回或者或引發(fā)未在函數(shù)中處理的異常的時候被刪除;
  • 4 查看命名空間
    查看全局命名空間: globals()
    查看本地命名空間: locals()
    查看內建的命名空間:以Python3為例:import builtins builtins.__dict__

二、作用域

1.介紹

作用域是Python程序(文本)的某一段或某些段,在這些地方,某個命名空間中的名字可以被直接訪問。這個作用域就是這個命名空間的作用域。

直接訪問:對一個變量名的引用會在所有namespace中查找該變量,而不是通過屬性訪問.
屬性訪問:所有名字后加 . 的都認為是屬性訪問.

如 module_name.func_name ,需要指定 func_name 的名空間,屬于屬性訪問。
而 abs(-1) , abs 屬于直接訪問。

作用域 盡管范圍是靜態(tài)確定的,但它們是動態(tài)使用的。在執(zhí)行期間的任何時間,至少有三個嵌套的作用域,其命名空間可以直接訪問。

2. 四個作用域

四個作用域分別是:

Local:包含局部變量。比如一個函數(shù)/方法內部。
Enclosing:包含了非局部(non-local)也非全局(non-global)的變量.比如兩個嵌套函數(shù),內層函數(shù)可能搜索外層函數(shù)的namespace,但該namespace對內層函數(shù)而言既非局部也非全局。
Global:當前腳本的最外層。比如當前模塊的全局變量。
Built-in:Python __builtin__ 模塊(python3中改為builtins模塊).包含了內建的變量/關鍵字/函數(shù)等.

3. 著名的”LEGB-rule”,即scope的搜索順序

Local -> Enclosing -> Global -> Built-in

假設有個變量處于函數(shù)里面:當有一個變量在 local 域中找不到時,Python會找上一層的作用域,即 enclosing 域(該域不一定存在)。
enclosing 域還找不到的時候,再往上一層,搜索模塊內的 global 域
最后,會在 built-in 域中搜索。對于最終沒有搜索到時,Python會拋出一個 NameError 異常。

4. global 和 nonlocal

global 用來聲明 一個變量 是 屬于 全局作用域
nonlocal 用來 聲明 一個變量 屬于 Enclosing 作用域

代碼1:

def outer():
    b = 1  # 此處 b 處于 Enclosing 作用域

    def inner():
        global b

        b += 1  # 在 inner 函數(shù)里面想要修改 outer函數(shù) b變量的值。
        print('inner_b is %d' % b)

    inner()
    print('outer_b is %d' % b)


outer()

# 拋出 NameError: global name 'b' is not defined

代碼2:

def outer():
    b = 1

    def inner():
        b = b + 1  # 此時 b 變量所在的命名空間屬于 local作用域
        print('inner_b is %d' % b)

    inner()
    print('outer_b is %d' % b)


outer()

# 拋出 UnboundLocalError: local variable 'b' referenced before assignment

代碼3:

def outer():
    b = 1

    def inner():
        nonlocal b
        b = b + 1
        print('inner_b is %d' % b)

    inner()
    print('outer_b is %d' % b)


outer()
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容