定義:函數內部函數對外部做用域而非全局做用域的引用閉包
使用參數app
def func(x) print(x) func(1) func(1)
1 1
def outter(x) def inner() print(x) return inner f = outter(1) f()
1
閉包的意義:返回的函數對象,不單單是一個函數對象,在該函數外還包裹了一層做用域,這使得,該函數不管在何處調用,優先使用本身外層包裹的做用域。函數
import requests def outter(url): def get(): response = requests.get(url) print(f'done:{url}') return get baidu=outter('https:www.baidu.com') baidu()
done: https://www.baidu.com
裝飾器指:未被裝飾器對象添加額外的功能。url
注意:1,裝飾器自己實際上是能夠任意可調用的對象code
2,被裝飾的對象能夠是任意可調用的對象對象
爲何須要裝飾器ip
若是咱們已經上線了一個項目,咱們須要修改某一個方法,可是咱們不想修改方法的使用方法,這個時候能夠使用裝飾器。由於軟件的維護應該遵循開放封閉原則,即軟件一旦上線運行後,軟件的維護對修改源代碼是封閉的,對擴展功能指的是開放的。作用域
注意:1,不修改被裝飾對象的源代碼get
2,不修改被裝飾對象的調用方式
怎麼用裝飾器
傳參方式:改變調用方式
傳參方式:包給函數——外包
mport time def time_count(func): # func = 最原始的index def wrapper(*args, **kwargs): start = time.time() res = func(*args, **kwargs) end = time.time() print(f"{func} time is {start-end}") return res return wrapper @time_count # home = time_count(home) def home(name): print(f"welcome {name} to home page") time.sleep(1) return name @time_count # index = time_count(index) def index(): print('welcome to index') time.sleep(1) return 123 res = home('egon') print(f"res: {res}")
welcome egon to home page <function home at 0x102977620> time is -1.0005171298980713 res: egon
def deco(func): def wrapper(*args,**kwargs) res = func(*args,**kwargs) return res return wrapper
is_login_dict = {'username':None} def login_deco(func): def wrapper(*args,**kwargs): if not is_login_dict['username']: username = input('請輸入你的用戶名').strip() if username != 'john': print('非法輸入') return is_login_dict['username']=username res = func(*args,**kwargs) return res else: res = func(*args,**kwargs) return res return wrapper @login_deco def withdraw(): print('from withdraw') withdraw() withdraw() withdraw()
有參裝飾器
is_login_dict = {'username': None} def auth(origin): def login_deco(func): def wrapper(*args, **kwargs): # 賦值後的time_sleep if origin == 'file': if not is_login_dict['username']: username = input('請輸入你的用戶名》》》').strip() if username != 'fanping': print('非法登陸') return is_login_dict['username'] = username res = func(*args, **kwargs) # 真正的time_sleep return res else: res = func(*args, **kwargs) # 真正的time_sleep return res elif origin == 'mongodb': print('非法登陸') else: print('dsb') return wrapper return login_deco # f = origin('file') # login_deco # shopping = f(shopping) # shopping() @auth('file') def shopping(): print('from shopping') @auth('mongodb') def withdraw(): print('from withdraw')
注意:裝飾器給函數增長功能嗎,可是不改變函數內部的語法,不改變函數調用方式