21.閉包 1. 閉包:在嵌套函數內,使用非全局變數(且不使用本層變數) 2. 閉包的作用:1.保證數據的安全性(純潔度)。2.裝飾器使用 3. ._\_closure\_\_判斷是否是閉包 22.裝飾器一(入門) 1.一個裝飾器裝飾多個函數 開放封閉原則:擴展是開放的(增加新功能),源碼是封閉的( ...
21.閉包
- 閉包:在嵌套函數內,使用非全局變數(且不使用本層變數)
- 閉包的作用:1.保證數據的安全性(純潔度)。2.裝飾器使用
- .__closure__判斷是否是閉包
def func():
a = 1
def foo():
print(a)
return foo
ret = func()
ret()
#例子
def func():
avg_lst = []
def foo(pirce):
avg_lst.append(pirce)
avg = sum(avg_lst) / len(avg_lst)
return avg
return foo
ret = func()
print(ret(1500))
print(ret(1600))
print(ret.__closure__)#結果:(<cell at 0x000002095400B558: list object at 0x00000209540A5B48>,)證明是閉包
print(func.__closure__)#結果:None,不是閉包
print(ret.__code__.co_freevars)#獲取的是自由變數
print(ret.__code__.co_varnames)#獲取的是局部變數
22.裝飾器一(入門)
1.一個裝飾器裝飾多個函數
開放封閉原則:擴展是開放的(增加新功能),源碼是封閉的(修改已經實現的功能)
作用:在不改變源代碼及調用方式的基礎下額外增加新功能。
裝飾器:用來裝飾的工具
2.版一:
import time
start_time = time.time
def func():
time.sleep(2)#睡眠s模擬網路延時
print("我要飛")
func()
print(time.time - start_time)
#改變了源代碼
3.版二:
def times(f):
start_time = time.time()
f()
print(time.time() - start_time)
def foo():
time.sleep(3)
print("我飛的比你高")
#times(foo)#改變了調用方式
s = foo
foo = times
foo(s)#不改變調用方式
4.版三:(low版裝飾器)
def times(f):
def inner():
start_time = time.time()
f()
print(time.time() - start_time)
return inner
def foo():
time.sleep(3)
print("我飛的比你高")
foo = times(foo)
foo()
5.版四:
def wrapper(f):
def inner(a):
start_time = time.time()
f(a)
print(time.time() - start_time)
return inner#切記不加括弧
def func(a):
print(f"{a}你不行")
func = wrapper(func)
func("alex")
#傳輸多個數據,用*args,**kwargs
6.版五(標準版裝飾器):
@wrapper#語法糖:必須放在要裝飾的函數的正上方
def wrapper(f):#f是要被裝飾的函數名
def inner(*args,**kwargs):
"被裝飾前"
start_time = time.time()
ret = f(*args,**kwargs)
print(time.time() - start_time)
"被裝飾後"
return ret
return inner#切記不加括弧
@wrapper#語法糖 -->func = wrapper(func)
def func(*args,**kwargs):
print(f"{a}你不行")
return "我可以返回了"
#func = wrapper(func)#有語法糖不用多次賦值
func("alex")
23.裝飾器二(進階)
1.有參裝飾器:
有參裝飾器:在基礎裝飾器的基礎上再套一層函數
#有參裝飾器實現登陸驗證
msg = """
QQ
微信
抖音
請輸入您要登錄的的app:
"""
chose = input(msg).upper()
dict_flag = {'username':None,'flag':False}
def auth(a):
def wrapper(f):
def inner(*args,**kwargs):
if dic_flag['flag']:
fun(*args,**kwargs)
else:
if argv =="QQ":
print("歡迎登陸QQ")
user = intput("user:")
pwd = input("passwd:")
if user == "alex" and pwd == "alex123":
dict_flag["flag"] = True
dict_flag["username"] = user
foo(*args,**kwargs)
else:
print("用戶名或密碼錯誤!")
return inner
return wrapper
@auth(chose)
"""
語法糖拆分:
wrapper = auth(chose)
foo = wrapper(foo)
"""
def foo():
print("這是被裝飾的函數")
foo()
2.多個裝飾器裝飾一個函數:
當被裝飾的函數正上方有多個裝飾器,先執行里被裝飾函數最近的裝飾器(小技巧:進入裝飾器,從上往下,走到最後一個裝飾器,執行被裝飾的函數,退出裝飾器從下往上)
def wrapper1(f):
def inner1(*args,**kwargs):
print("這是第一個裝飾器開始")
f(*args,**kwargs)
print("這是第一個裝飾器結束")
return
return inner1
def wrapper2(f):
def inner2(*args,**kwargs):
print("這是第二個裝飾器開始")
f(*args,**kwargs)
print("這是第二個裝飾器結束")
return
return inner2
@wrapper1
@wrapper2
"""
兩個語法糖等價於:
foo = wrapper2(foo)#foo == inner2
foo = wrapper1(foo)#foo = wrapper(inner2),foo == inner1
foo()#-->inner1()
"""
def foo():
print("這是被裝飾的函數")
foo()
'''
結果:
這是第一個裝飾器開始
這是第二個裝飾器開始
這是被裝飾的函數
這是第二個裝飾器結束
這是第一個裝飾器結束
'''