Python函數2
一、命名空間:
什麽是命名空間:
--> Python代碼在執行的過程中從上到下順序執行,
--> 從python解釋器開始執行之後,就在內存中開辟了一個空間。
--> 每當遇到一個變量的時候,就把變量名和值之間的對應關系記錄下來。
--> 但是,當遇到函數的時候,Python解釋器只是將函數名稱讀入內存,並且知道這個函數已經存在了,此時,函數內部的變量和邏輯關系解釋器根本就不關心,並沒有執行函數內部的代碼
--> 等到執行函數的調用的時候,Python解釋器才會在內存中再開辟一塊兒空間,來存儲函數裏面的代碼內容,這個時候,才會關註函數內部有哪些變量。函數內部的變量存儲在新開辟的空間中,只能供函數內部使用,等函數執行完畢,這塊兒內存空間中所有內容都會被清空。
--> 我們給這個“存放名字與值的關系”的空間起了一個名字——叫做命名空間
命名空間分為三種:全局命名空間,局部命名空間,內置命名空間。
1.首先先說下內置命名空間:裏面包含了Python解釋器為我們提供的一些名字。比如:input,print,list,tuple等等。我們直接拿過來用就可以。
2.全局命名空間:代碼在運行伊始,創建的存儲“變量名與值的關系”的空間叫做全局命名空間。
3.局部命名空間:在函數的運行中開辟的臨時的空間叫做局部命名空間。
命名空間的加載順序:內置命名空間(程序運行前加載)->全局命名空間(程序運行中:從上到下加載)->局部命名空間(程序運行中:調用時才加載)
關於作用域:作用域就是作用範圍,按照生效範圍可以分為全局作用域和局部作用域。
全局作用域:包含內置命名空間和全局作用空間,在整個文件的任意位置都能被引用、全局有效
局部作用域:局部名稱空間,只能在局部範圍內使用
關於global關鍵字
來看一段代碼:
a = 1 def func(): a = 20 print(a) func() print(a)
上面的代碼打印結果
1 1
第一個 print(a)在調用函數之前打印 a 的值,打印 1 ,後面調用函數,在函數內部,明明已經修改了 a的值,後面打印 還是打印 1 。其實,第一個 a = 1.這個a 是全局命名空間。在函數內部 a = 20 ,這個a是局部命名空間,如果想在函數內部,對全局變量的值做修改,可以使用關鍵字 global
a = 1 def func(): global a a = 20 print(a) func() print(a)
這次的打印結果
1 20
二、關於函數的探討
先看一段代碼:
def func(): # 定義一個函數 pass f = func # 將函數名稱賦值給一個變量 print(func) # 打印函數名稱 print(f) # 打印變量 f
執行結果
<function func at 0x000000000050C1E0> # 翻譯結果:0x000000000050c1e0處的函數func <function func at 0x000000000050C1E0>
從結果中可以看出:函數名稱實際上存放的是這個函數的一個內存地址,另外,函數名也可以賦值給一個變量,其實函數名也是一個變量
既然函數名本質上其實就是一個變量,那麽,函數名也就可以作為容器中的一個元素。如:
def func1(): pass def func2(): pass def func3(): pass list_func = [func1,func2,func3] for l_func in list_func: print(l_func)
打印結果
<function func1 at 0x00000000003DC1E0> <function func2 at 0x0000000002718510> <function func3 at 0x0000000002718598>
也可以當做函數的參數以及返回值
def outer(): name = ‘jack‘ def inner(): print(name) return inner outer()
三、閉包:內部函數包含對外部作用域而非全劇作用域名字的引用,該內部函數稱為閉包函數
來看一段代碼
def outer(x): def inner(y): return x + y print(inner.__closure__) # 使用__closure__ 判斷是否為閉包,如果輸出包含cell 則是閉包。如果輸出為None 則不是閉包 return inner f = outer(9) print(type(f)) # 打印f的類型 print(f.__name__) # 輸出 f 的名字
輸出結果
(<cell at 0x00000000021DB858: int object at 0x000007FEDFC5D520>,) <class ‘function‘> inner
結合這段簡單的代碼和定義來說明閉包:
如果在一個內部函數裏:inner(y)就是這個內部函數,對外部作用域(但不是在全局作用域)的變量進行引用:x就是被引用的變量(x在外部作用域outer裏面,但是不是全局作用域),name這個內部函數就是一個閉包
使用閉包的註意事項:
在閉包中,是不能修改外部作用域的變量的值
def outer(): a = 0 def inner(): a = 1 print(a) print(a) inner() return inner outer()
打印結果
0
1
另外需要註意的一點是:閉包不要引用任何的循環變量,或者後續會發生變化的變量
Python函數2