準備知識: 1.在Python解釋器開始執行以後,機會在內存中開闢一個空間,每當遇到 一個變量的時候,就把變量和值之間的關係記錄下來,可是當遇到函數定義 的時候,解釋器只是把函數名讀入內存,表示這個函數存在,至於函數內部 的變量和邏輯,解釋器是不關心的。也就是說一開始的時候函數只是加載進 來,僅此而已,只有當函數被調用和訪問的時候解釋器纔會根據函數內部聲 明的變量來進行開闢變量的內部空間。隨着函數執行完畢,這些函數內部變 量佔用的空間也會隨着函數執行完畢而清空。 例子: def fun(): a = 10000 print(a) fun() print(a) # a不存在了了已經.. 2.命名空間 在一個Python程序的任何一個地方,都存在幾個可用的命名空間。 咱們存放名字和值的關係的空間起個名字,叫命名空間。 咱們的變量在存儲的時候就存在這片空間的。 (1)分類: 1)每一個函數都有本身的命名空間,叫作局部命名空間, 它記錄了函數的變量,包括函數的參數和局部定義的變量。 2)每一個模塊都擁有本身的命名空間,叫作全局命名空間, 它記錄了模塊的變量,包括函數、類、其餘導入的模塊、 模塊級的變量和常量。 3)還有就是內置命名空間,任何模塊都可訪問,它存放着 內置的函數和異常。 加載順序:內置命名空間,全局命名空間,局部命名空間(函數被執行) 取值順序:局部命名空間,全局命名空間,內置命名空間 注意:嵌套函數的狀況 1.先在當前(嵌套的或lambda)函數的命名空間搜索 2.而後是在父函數的命名空間中搜索 3.接着是模塊命名空間中搜索 4.左後在內置命名空間中搜索 (2)生命週期: 命名空間的生命週期不一樣的命名空間在不一樣的時刻建立, 有不一樣的生存期。 一、內置命名空間在 Python 解釋器啓動時建立, 會一直保留,不被刪除。 二、模塊的全局命名空間在模塊定義被讀入時建立, 一般模塊命名空間也會一直保存到解釋器退出。 三、當函數被調用時建立一個局部命名空間,當函 數返回結果或拋出異常時,被刪除。每個遞歸 調用的函數都擁有本身的命名空間。 3.做用域 L :local,局部做用域,即函數定義的變量 E :enclosing,嵌套的父級函數的局部做用域, 即包含此函數的上級函數的局部做用域但不是全局 G :global, 全局變量,就是模塊級別定義的變量。 B :built-in,系統固定模塊裏面的變量。好比int等。 搜索變量的優先級順序:LEGB 1.globals() 和 locals() globals() 獲取到全局做用域(內置,全局)中的全部名字 locals() 查看當前做用域中的全部名字 例子: a = 10 def func(): a = 20 print(a) # 就近原則 print(globals()) # globals() 獲取到全局做用域(內置,全局)中的全部名字 print(locals()) # locals() 查看當前做用域中的全部名字 func() 打印內容: (1)#20 (2)#{'__name__': '__main__', '__doc__': None, '__package__': None, # '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x10cee7400>, # '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, #'__file__': '/Users/busensei/wzy/test.py', '__cached__': None, 'a': 10, #'func': <function func at 0x10ce6eea0>} (3)#{'a': 20} 2. global 和 nonlocal global:尋找全局做用域中的內容(聲明在局部做用域裏使用全局做用域的變量) nolocal :聲明在局部做用域裏,使用上層局部做用域的變量, 且上層不能夠是全局變量 經過例子來加深理解: <1> a = 10 def func(): global a # a 再也不是局部變量. 是全局變量 a = 30 # 把全局中的a從新賦值成30 print(a) #30 func() print(a) #30 <2> a = 10 def func1(): a = 40 def func2(): nonlocal a # 找局部做用域中 離他最近的那個變量引入進來 a = 20 print(a)#20 這時被引入的變量a的值從40變成了20 func2() print(a)#20 這時這層的a已經被20所覆蓋 func1() print(a)#10 nonlocal是在他外層找到值中止,若是沒有到全局就回報錯,不會到全局 結果: 20 20 10 <3> a = 10 def fun1(): a = 20 def fun3(): def fun2(): nonlocal a a = a + a print(a)#40 fun2() fun3() print(a)#40 fun1() print(a)#10 結果: 40 40 10 <4> a = 10 def fun1(): def fun3(): b = 30 def fun2(): global a nonlocal b a = a + b print(a)#40 fun2() fun3() print(a)#40 fun1() print(a)#40 結果: 40 40 40 <練習> a = 1 def fun_1(): a = 2 def fun_2(): nonlocal a a = 3 def fun_3(): a = 4 print(a) print(a) fun_3() print(a) print(a) fun_2() print(a) print(a) fun_1() print(a) 結果: 1 2 3 4 3 3 1