python函數下篇裝飾器和閉包,外加作用域
阿新 • • 發佈:2017-06-20
發揮 作用域 fat 功能 user div 日誌 code 返回函數
裝飾器和閉包的基礎概念
裝飾器是一種設計模式能實現代碼重用,經常用於查日誌,性能測試,事務處理等,抽離函數大量不必的功能。 裝飾器:
1、裝飾器本身是一個函數,用於裝飾其它函數:
2、功能:增強被裝飾函數的功能。
裝飾器需要遵循的原則
1.不修改被裝飾函數的源代碼(開放封閉原則) 2.為被裝飾函數添加新功能後,不修改被裝飾函數的調用方式
裝飾器 = 高階函數+函數嵌套+閉包
高階函數
1.函數接受的參數是一個函數名 2.函數的返回值是一個函數名 3.只有上述條件滿足一個就是高階函數
def foo(): print(‘高階函數實例,被調用的函數‘) def func(foo):print(‘調用上面的函數‘) foo() func(foo)
把函數名當做參數傳給告誡函數,告誡函數直接返回函數名
import time def foo(): print(‘from the foo‘) def timmer(func): start_time = time.time() return func stop_time = time.time() print(‘函數%s運行時間是%s‘)%(func,stop_time - start_time) foo = timmer(foo) foo()
高階函數總結 1.函數接收的參數是一個函數名
作用:在不修改函數源代碼的前提下,為函數添加新功能
不足:會改變函數的調用方式
2.函數的返回值是一個函數名
作用:不修改函數的調用方式
不足:不能添加新功能
嵌套函數
def father(name): print(‘from father %s‘%name) def son(): print(‘from son‘) def grandson(): print(‘from grandson‘) grandson() son() father(‘逗逼‘)
閉包函數:函數在嵌套環境中,如果在內層函數裏,對外層函數作用域中的變量進行引用,在外層函數返回後內層函數依然可以使用外層函數中的變量,這種變量就構成了內層函數可以使用的環境。所以閉包對隱藏狀態,以及在函數對象和作用域中隨意切換,一個函數可以發揮N種功用
def f1(x): def f2(y): return y ** x return f2 f1(4) f3=f1(3) type(f3) f3(4) def startPos(m,n): def newPos(x,y): print(‘‘The old position is (%d,%d), and the new position is (%d,%d)"%(m,n,m+x,n+y)) return newPos action = startPos(10,10) action(1,2) action(-1,3) #結果 <function f1.<locals>.f2 at 0x02125270> <class ‘function‘> 64 The old position is (10,10),and the new position is (11,12) The old position is (10,10),and the new position is (9,13)
無參裝飾器
無參裝飾器 = 高級函數 + 函數嵌套 基本框架
#這就是一個實現一個裝飾器最基本的架子 def time(func): def wrapper(): func() return wrapper 加上參數 def timer(func): def wrapper(*args,**kwargs): func(*args,**kwargs) return wrapper 加上功能 import time def timer(func): def wrapper(*args,**kwargs): start_time = time.time() func(*args,**kwargs) stop_time = time.time() print(‘函數[%s],運行時間是[%s]‘%(func,stop_time-start_time)) return wrapper 加上返回值 import time def timer(func): def wrapper(*args,**kwargs): start_time = time.time() res = func(*args,**kwargs) stop_time = time.time() print(‘函數[%s],運行時間是[%s]‘%(func,stop_time-start_time)) return res return wrapper 使用裝飾器 def cal(arry): res = 0 for in in array: res+=i return res cal = timer(cal) cal(range(10) 語法糖@ @timer def cal() def cal(array): res=0 for i in array: res+=i return res cal(range(10)) 有參裝飾器 user_list=[ {‘name‘:‘alex‘,‘passwd‘:‘123‘}, {‘name‘:‘linhaifeng‘,‘passwd‘:‘123‘}, {‘name‘:‘wupeiqi‘,‘passwd‘:‘123‘}, {‘name‘:‘yuanhao‘,‘passwd‘:‘123‘}, ] current_user={‘username‘:None,‘login‘:False} def auth(auth_type=‘file‘): def auth_deco(func): def wrapper(*args,**kwargs): if auth_type == ‘file‘: if current_user[‘username‘] and current_user[‘login‘]: res = func(*args,**kwargs) return res username = input(‘用戶名:‘).strip() passwd = input(‘密碼:‘).strip() for index,user_dic in enumerate(user_list): if username == user_dic[‘name‘] and passwd ==username[‘passwd‘]: current_user[‘username‘] =username current_user[‘login‘]=True res = func(*args,**kwargs) return res break else: print(‘用戶名或者密碼錯誤,重新登錄‘) elif auth_type ==‘ldap‘: print(‘登錄成功‘) res = func(*args,**kwargs) return res return wrapper return auth_deco @auth(auth_type=‘ldap‘) def index(): print(‘歡迎來到主頁面‘) @auth(auth_type=‘ldap‘) def home(): print(‘家目錄‘) def shopping_car(): print(‘購物車頁面‘) def order(): print(‘訂單頁面‘) index() home()
作用域規則 每次執行執行一個函數時,就會創建新的局部命名空間。該命名空間代表一個局部環境,其中包含函數參數的名稱和在函數體內賦值的變量名稱。解析這些名稱 時,解釋器首先搜索局部命名空間、如何沒有找到匹配的名稱,它就會搜索全局命名空間。函數的全局命名空間始終是定義該函數的模塊。如果解釋器在全局命名空間中也找不到匹配值,最終會檢查內置命名空間。如果仍然找不到,就會引發NameError異常
python函數下篇裝飾器和閉包,外加作用域