🍖名稱空間與做用域

引入

棧區 / 堆區

  • 棧區 : 存放的是變量名與變量值的內存地址映射關係
  • 堆區 : 存放的是值真正的位置

棧區和堆區

一.名稱空間

1.什麼是名稱空間

  • 存放名字與值綁定關係的地方
  • 名稱空間是一個虛擬的概念, 棧區才真實存在

2.爲何要有名稱空間

  • 有了名稱空間後就能夠在內存的棧區存放相同的名字, 而且不會衝突

3.名稱空間是否有包含關係?

  • 名稱空間本質之間是沒有包含關係的, 而且相互獨立

名稱空間的關係

二.名稱空間的分類(三類)

1.內置名稱空間

  • 存放內置的名字
  • 週期 : 在解釋器啓動時就產生,解釋器關閉則失效
🎅例如咱們經常使用的內置函數
print
len
input

2.全局名稱空間

  • 存放的是頂級的名字 (文件級別的名字)
  • 週期 : 在執行文件時生效,文件運行完畢或文件執行期間被刪除則失效
x = 1      #全局名稱空間
def foo(): #全局名稱空間
	y = 2

🎅注意,"if"下面的定義的變量名都是全局的
if 1 > 0        
	z = 3        #全局
	if 3 > 0: 
		p = 555  #全局

3.局部名稱空間

  • 存放函數內定義的名字
  • 週期 : 在函數調用時臨時生效, 函數結束時則失效
def f()
	x = 222    #局部名稱空間
    
f()   #函數調用結束失效

4.名稱空間的加載順序

'內置名稱空間'----->'全局名稱空間'----->'局部名稱空間'

5.名稱空間的查找優先級

'局部名稱空間'----->'全局名稱空間'----->'內置名稱空間'

6.名稱空間的銷燬順序

'局部名稱空間'----->'全局名稱空間'----->'內置名稱空間'

7.名稱空間總結與注意事項

  • 重要概念:名稱空間的嵌套關係是在函數定義階段(檢測語法)時肯定的,與函數調用的位置無關,與函數定義位置有關python

  • 三種名稱空間必需要有的是 : 內置名稱空間, 全局名稱空間閉包

  • 查找優先級示例函數

🎅從"f2"局部開始找
x = 3
def f1():
    x = 2
    def f2():
        x =1
        print(x)
    f2()
f1()  # 1

🎅將"f2"局部的刪除,就往上一層找,找到"f1"
x = 3
def f1():
    x = 2
    def f2():
        print(x)
    f2()
f1()  # 2

🎅再將"f1"裏面的刪除,因而找到了全局
x = 3
def f1():
    def f2():
        print(x)
    f2()
f1()  # 3
  • 函數的嵌套定義示例
🎅在定義"f2"的以後,有定義了同一級別的"len",因此當打開函數"f2"運行的時候,本着優先級查找就先找到了"222"
len = 111
def f1():
    def f2():
        print(len) # 222
	len = 222
    f2()
f1()  # 222

三.做用域

1.什麼是做用域

  • 做用域就是根據名稱空間的範圍和特色進行了歸類
  • 查看做用域 : globals( ), locals( )

2.全局做用域

  • 包含 : 內置名稱空間, 全局名稱空間
  • 特色 : 全局存活, 全局有效

3.局部做用域

  • 包含 : 局部名稱空間
  • 特色 : 臨時存活, 局部有效

4.L E G B

  • LEGB 表明名字查找順序 : L--->E--->G--->B
  • locals : 是函數內的名字空間, 包括局部變量和形參
  • enclosing : 外部嵌套的名稱空間(閉包中常見面)
  • globals : 全局變量, 函數定義所在模塊的名字空間
  • builtins : 內置模塊的名字空間

四.global 與 nonlocal關鍵字

1.global 關鍵字

  • 使用方法 : global x 聲明這個 x 是全局變量
  • 針對的是不可變類型的值
🎅在全局空間定義一個變量"x",函數"foo",在函數內部修改"x"的值
x = 111
def foo():
    x = 222
    
foo()
print(x)   #111
#發現並沒有軟用

🎅使用"global"關鍵字以後
x = 111
def foo():
    global x  # 聲明下面的"x"屬於全局
    x = 222
    
foo()
print(x)  #222
#發現成功了

2.nonlocal 關鍵字

  • 使用方法 : nonlocal x
  • 修改該函數外層函數包含的變量名對應的值, 也是針對不可變類型
  • 注意 : 只能在局部名稱空間中查找, 先從外部嵌套的函數找, 沒找到再往上找, 若是都沒找到則報錯
🎅不作任何處理,此函數應該是打印"f2"函數下的"x = 333"
x = 111
def f1():
    x = 222
    def f2():
        x = 333
        def f3():
            x = 444
        f3()
        print(x)  #333
    f2()
f1()  # 333

🎅使用"nonlocal"關鍵字
x = 111
def f1():
    x = 222
    def f2():
        x = 333
        def f3():
            nonlocal x  #將下面的"x = 444"變成了上一層的"x"的值
            x = 444
        f3()
        print(x) 
    f2()
f1()  # 444

🎅若是外層函數都沒有"x"這個值,報錯
x = 111  #並不會去全局修改
def f1():
    def f2():
        def f3():
            nonlocal x
            x = 444
        f3()
        print(x)
    f2()
f1()  #報錯
相關文章
相關標籤/搜索