Python命名空間和做用域

準備知識:
	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
相關文章
相關標籤/搜索