閉包:內(nèi)部函數(shù)的參數(shù)調(diào)用外部函數(shù)的參數(shù)就是一個(gè)閉包
def A():
????a = 1
????def B():
????????print(a)
????return B #
a = A()
a()
這樣的一個(gè)函數(shù)就構(gòu)成了閉包函數(shù)
例子說明去理解閉包和裝飾器之間的關(guān)系
from functools import wraps
def wrapper(f):
????@wraps(f)
????def inner(*args, **kwargs):
????????ret = f(*args, **kwargs)
????????return ret
????return inner
@wrapper? # func = wrapper(func) wrapper函數(shù)
def func(a, b, c, d=1234):
????print(a, b, c, d)
????return "Hello World"
-------------------------------------結(jié)果----------------------------------------
print(func.__name__)
if func.__doc__:
print("True")
--------------------------------------------------------------------------------
*args 是接受任意數(shù)據(jù)類型
**kwargs是接受位置參數(shù) 比如a=1 ,b =4
@wrapper其實(shí)就是去執(zhí)行wrapper函數(shù)把func當(dāng)成參數(shù)去執(zhí)行,func進(jìn)入wrapper之后,本質(zhì)上就是執(zhí)行了inner函數(shù)。
-------------------------------------------------------------------------------------
加深小練習(xí):
編寫裝飾器,為多個(gè)函數(shù)加上認(rèn)證功能(用戶的賬號(hào)密碼來源于文件)要求登錄成功一次 后續(xù)的函數(shù)都無需輸入用戶名和密碼
FLAG = False
def login(f):
????def inner(*args, **kwargs):
????global FLAG
????if FLAG:
????????ret = f(*args, **kwargs)
????????return ret
????else:
????????username = input("username:")
????????password = input("password:")
????????if username == 'admin' and password == '1234':
????????????FLAG = True
????????????ret = f(*args, **kwargs)
????????????return ret
????????else:
????????????print("錯(cuò)誤!")
????return inner
@login
def shoplist_add():
????print("add")
@login
def shoplist_delete():
? ? print("delete")
-----------------------------------------------------------------------------------
# 編寫裝飾器 為多個(gè)函數(shù)加上記錄調(diào)用功能,要求每次調(diào)用函數(shù)都將被調(diào)用的函數(shù)名稱寫入文件
def log(func):
????def inner(*args, **kwargs):
????????with open('log', 'a', encoding='utf-8') as f:
????????????f.write(func.__name__ + '\n')
???????????ret = func(*args, **kwargs)
????????????return ret
????????return inner
@log? # shoplist_add = log(shoplist_add)
def shoplist_add():
????print("add")
@log
def shoplist_delete():
????print("delete")
shoplist_delete()
shoplist_add()
-------------------------------------------------------------------------------------
#.1編寫下載網(wǎng)頁內(nèi)容的函數(shù) 要求功能是: 用戶傳入一個(gè)url 函數(shù)返回下載頁面的結(jié)果2.為題目1編寫裝飾器 實(shí)現(xiàn)緩存網(wǎng)頁中歐內(nèi)容的功能
具體 實(shí)現(xiàn)下載的頁面存放與文件中 如果文件內(nèi)有值(文件大小不為0)就優(yōu)先從文件中讀取網(wǎng)頁內(nèi)容 否則就去下載'''
import os
from urllib.request import urlopen
def cache(func):
????def inner(*args, **kwargs):
????????if os.path.getsize('web_Cache'):
????????????with open('web_Cache','rb')as f:
????????????????return f.read()
????????ret = func(*args, **kwargs)
????????with open('web_Cache','wb') as f:
????????????f.write(b'*********' + ret)
????????return ret
????return inner
@cache # get = cache(get)
def get(url):#inner
? ? code = urlopen(url).read()
return code
# {'網(wǎng)址':"文件名"}
url ='https://baike.baidu.com/item/%E5%A4%A7%E4%BD%AC/33459'
ret = get(url)
print(ret)
ret = get(url)
print(ret)
python裝飾器進(jìn)階代碼:
import time
Flag =True
def contrl_flag(flag):
????def timer(func):
????????def inner(*args, **kwargs):
????????????if flag:
????????????????start = time.time()
????????????????ret = func(*args, **kwargs)
????????????????end = time.time()
????????????????print(end - start)
????????????????return ret
???????????else:
????????????????ret = func(*args, **kwargs)
????????????????return ret
????????return inner
????return timer
@contrl_flag(Flag)
def test1():# @timer = timer(test1)
? ? time.sleep(0.1)
print("test1")
@contrl_flag(Flag)
def test2():
????time.sleep(0.1)
????print("test2")
test1()
test2()