#1 能夠被引用 #2 能夠看成參數傳遞 #3 返回值能夠是函數 #3 能夠看成容器類型的元素
二 利用該特性,優雅的取代多分支的if
def foo(): print('foo') def bar(): print('bar') dic={ 'foo':foo, 'bar':bar, } while True: choice=input('>>: ').strip() if choice in dic: dic[choice]()
def max(x,y): return x if x > y else y def max4(a,b,c,d): res1=max(a,b) res2=max(res1,c) res3=max(res2,d) return res3 print(max4(1,2,3,4))
def f1(): def f2(): def f3(): print('from f3') f3() f2() f1() f3() #報錯,爲什麼?請看下一小節
#名稱空間:存放名字的地方,三種名稱空間,(以前遺留的問題x=1,1存放於內存中,那名字x存放在哪裏呢?名稱空間正是存放名字x與1綁定關係的地方)python
二 名稱空間的加載順序閉包
python test.py #一、python解釋器先啓動,於是首先加載的是:內置名稱空間 #二、執行test.py文件,而後以文件爲基礎,加載全局名稱空間 #三、在執行文件的過程當中若是調用函數,則臨時產生局部名稱空間
局部名稱空間--->全局名稱空間--->內置名稱空間 #須要注意的是:在全局沒法查看局部的,在局部能夠查看全局的,以下示例
# max=1
def f1(): # max=2
def f2(): # max=3
print(max) f2() f1() print(max)
#一、做用域即範圍
- 全局範圍(內置名稱空間與全局名稱空間屬於該範圍):全局存活,全局有效 - 局部範圍(局部名稱空間屬於該範圍):臨時存活,局部有效 #二、做用域關係是在函數定義階段就已經固定的,與函數的調用位置無關,以下
x=1
def f1(): def f2(): print(x) return f2 x=100
def f3(func): x=2 func() x=10000 f3(f1()) #三、查看做用域:globals(),locals()
LEGB 表明名字查找順序: locals -> enclosing function -> globals -> __builtins__ locals 是函數內的名字空間,包括局部變量和形參 enclosing 外部嵌套函數的名字空間(閉包中常見) globals 全局變量,函數定義所在模塊的名字空間 builtins 內置模塊的名字空間
第二,二者使用的範圍不一樣。global關鍵字能夠用在任何地方,包括最上層函數中和嵌套函數中,即便以前未定義該變量,global修飾後也能夠直接使用,而nonlocal關鍵字只能用於嵌套函數中,而且外層函數中定義了相應的局部變量,不然會發生錯誤(見第一)。函數
#內部函數包含對外部做用域而非全局做用域的引用
#提示:以前咱們都是經過參數將外部的值傳給函數,閉包提供了另一種思路,包起來嘍,包起呦,包起來哇
def counter(): n=0 def incr(): nonlocal n x=n n+=1
return x return incr c=counter() print(c()) print(c()) print(c()) print(c.__closure__[0].cell_contents) #查看閉包的元素
#閉包的意義:返回的函數對象,不單單是一個函數對象,在該函數外還包裹了一層做用域,這使得,該函數不管在何處調用,優先使用本身外層包裹的做用域 #應用領域:延遲計算(原來咱們是傳參,如今咱們是包起來)
from urllib.request import urlopen def index(url): def get(): return urlopen(url).read() return get baidu=index('http://www.baidu.com') print(baidu().decode('utf-8'))