python基礎之函數進階
假如有一個函數,實現返回兩個數中的較大值:
def my_max(x,y): m = x if x>y else y return m
bigger = my_max(10,20)
print(bigger)
之前是不是我告訴你們要把結果return回來你們就照做了?可是你們有沒有想過,我們為什麽要把結果返回?如果我們不返回m,直接在程序中打印,行不行?
來看結果:
>>> def my_max(x,y): ... m = x if x>y else y ... >>> my_max(10,20) >>> print(m) Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name ‘m‘ is not defined
報錯了!錯誤是“name ‘m‘ is not defined”。變量m沒有被定義。。。為啥?我明明定義了呀!
在這裏我們首先回憶一下python代碼運行的時候遇到函數是怎麽做的。
從python解釋器開始執行之後,就在內存中開辟了一個空間
每當遇到一個變量的時候,就把變量名和值之間的對應關系記錄下來。
但是當遇到函數定義的時候解釋器只是象征性的將函數名讀入內存,表示知道這個函數的存在了,至於函數內部的變量和邏輯解釋器根本不關心。
等執行到函數調用的時候,python解釋器會再開辟一塊內存來存儲這個函數裏的內容,這個時候,才關註函數裏面有哪些變量,而函數中的變量會存儲在新開辟出來的內存中。函數中的變量只能在函數的內部使用,並且會隨著函數執行完畢,這塊內存中的所有內容也會被清空。
我們給這個“存放名字與值的關系”的空間起了一個名字——叫做命名空間
代碼在運行伊始,創建的存儲“變量名與值的關系”的空間叫做全局命名空間,在函數的運行中開辟的臨時的空間叫做局部命名空間
命名空間和作用域
在python之禪中提到過:命名空間是一種絕妙的理念,讓我們盡情的使用發揮吧!
命名空間一共分為三種:
全局命名空間
局部命名空間
內置命名空間
*內置命名空間中存放了python解釋器為我們提供的名字:input,print,str,list,tuple...它們都是我們熟悉的,拿過來就可以用的方法。
三種命名空間之間的加載與取值順序:
加載順序:內置命名空間(程序運行前加載)->全局命名空間(程序運行中:從上到下加載)->局部命名空間(程序運行中:調用時才加載)
取值:
在局部調用:局部命名空間->全局命名空間->內置命名空間
在局部使用變量取值情況
x = 1 def f(x): print(x) print(10)
在全局調用:全局命名空間->內置命名空間
在全局引用變量x
x = 1
def f(x): print(x) f(10) print(x)
在全局引用內置max
print(max)
作用域
作用域就是作用範圍,按照生效範圍可以分為全局作用域和局部作用域。
全局作用域:包含內置名稱空間、全局名稱空間,在整個文件的任意位置都能被引用、全局有效
局部作用域:局部名稱空間,只能在局部範圍內生效
globals和locals方法
在全局調用globals和locals
print(globals()) print(locals())
在局部調用globals和locals
def func():
a = 12 b = 20 print(locals()) print(globals()) func()
global關鍵字
a = 10 def func(): global a a = 20 print(a) func() print(a)
函數的嵌套和作用域鏈
函數的嵌套調用
def max2(x,y): m = x if x>y else y return m def max4(a,b,c,d): res1 = max2(a,b) res2 = max2(res1,c) res3 = max2(res2,d) return res3 # max4(23,-7,31,11)
函數的嵌套定義
def f1(): print("in f1") def f2(): print("in f2") f2() f1()
def f1(): def f2(): def f3(): print("in f3") print("in f2") f3() print("in f1") f2() f1()
python基礎之函數進階