一 函數是第一類對象,即函數能夠看成數據傳遞python
#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]()
一 函數的嵌套調用app
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))
二 函數的嵌套定義ide
def f1(): def f2(): def f3(): print('from f3') f3() f2() f1() f3() #報錯,爲什麼?請看下一小節
一 什麼是名稱空間?函數
#名稱空間:存放名字的地方,三種名稱空間,(以前遺留的問題x=1,1存放於內存中,那名字x存放在哪裏呢?名稱空間正是存放名字x與1綁定關係的地方)
二 名稱空間的加載順序ui
python test.py #一、python解釋器先啓動,於是首先加載的是:內置名稱空間 #二、執行test.py文件,而後以文件爲基礎,加載全局名稱空間 #三、在執行文件的過程當中若是調用函數,則臨時產生局部名稱空間
三 名字的查找順序url
局部名稱空間--->全局名稱空間--->內置名稱空間 #須要注意的是:在全局沒法查看局部的,在局部能夠查看全局的,以下示例 # max=1 def f1(): # max=2 def f2(): # max=3 print(max) f2() f1() print(max)
四 做用域spa
#一、做用域即範圍 - 全局範圍(內置名稱空間與全局名稱空間屬於該範圍):全局存活,全局有效 - 局部範圍(局部名稱空間屬於該範圍):臨時存活,局部有效 #二、做用域關係是在函數定義階段就已經固定的,與函數的調用位置無關,以下 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與nonlocal關鍵字3d
一 什麼是閉包?code
#內部函數包含對外部做用域而非全局做用域的引用 #提示:以前咱們都是經過參數將外部的值傳給函數,閉包提供了另一種思路,包起來嘍,包起呦,包起來哇 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'))
裝飾器就是閉包函數的一種應用場景
一 爲什麼要用裝飾器
#開放封閉原則:對修改封閉,對擴展開放
二 什麼是裝飾器
裝飾器他人的器具,自己能夠是任意可調用對象,被裝飾者也能夠是任意可調用對象。 強調裝飾器的原則:1 不修改被裝飾對象的源代碼 2 不修改被裝飾對象的調用方式 裝飾器的目標:在遵循1和2的前提下,爲被裝飾對象添加上新功能
三 裝飾器的使用
import time def timmer(func): def wrapper(*args,**kwargs): start_time=time.time() res=func(*args,**kwargs) stop_time=time.time() print('run time is %s' %(stop_time-start_time)) return res return wrapper @timmer def foo(): time.sleep(3) print('from foo') foo()
def auth(driver='file'): def auth2(func): def wrapper(*args,**kwargs): name=input("user: ") pwd=input("pwd: ") if driver == 'file': if name == 'egon' and pwd == '123': print('login successful') res=func(*args,**kwargs) return res elif driver == 'ldap': print('ldap') return wrapper return auth2 @auth(driver='file') def foo(name): print(name) foo('egon')
四 裝飾器語法
被裝飾函數的正上方,單獨一行 @deco1 @deco2 @deco3 def foo(): pass foo=deco1(deco2(deco3(foo)))
五 裝飾器補充:wraps
from functools import wraps def deco(func): @wraps(func) #加在最內層函數正上方 def wrapper(*args,**kwargs): return func(*args,**kwargs) return wrapper @deco def index(): '''哈哈哈哈''' print('from index') print(index.__doc__)