一 : 装饰器demo及分析
我们为函数添加一段附加功能,并且秉承着
- 不修改被修饰函数的源代码
- 不修改被修饰函数的调用方式
这种非常炫酷的添加附加功能的方式叫做装饰器
import time
#时间装饰器
def timmer(func):
def wapper(*args,**kwargs):
start_time = time.time()
res = func(*args,**kwargs)
stop_time = time.time()
print('函数时间是 : %s' % (stop_time - start_time))
return res
return wapper
@timmer
def cal(l):
res = 0
for i in l:
time.sleep(0.1)
res += i
return res
print(cal(range(20)))
函数时间是 : 2.0555498600006104
190
二 : 闭包
闭包说白了就是函数嵌套的另一种叫法,每层包都有自己的局部变量, 函数也要看成一种变量存放在自己那层的包中,每一层的嵌套 ,那一层就是一个包.
def first(name):
def second():
name = "222"
print(name)
def third():
name = "333"
print("哈哈哈"+name)
third()
print(name)
second()
first('111')
111
222
哈哈哈333
三 : 装饰器推导
装饰器 = 高阶函数 + 函数嵌套 + 闭包
① : 雏形
虽然没有修改foo函数源代码,也没有修改foo函数调用方式,但是运行结果却多执行了一次
def foo():
time.sleep(3)
print('来自foo')
def timer(func):
start_time = time.time()
func()
stop_time = time.time()
print("运行时间为 : "+str(stop_time - start_time))
return func
foo = timer(foo)
foo()
来自foo
运行时间为 : 3.002413034439087
来自foo
② : 闭包
利用闭包,(函数嵌套)将func
函数传入内部执行,返回wrapper
函数,赋值给test
,再运行test()
巧妙的解决了 步骤 ① 的问题
def timmer(func):
def wrapper():
start_time = time.time()
func()#运行test
stop_time = time.time()
print("运行时间" + str(stop_time - start_time))
return wrapper
def test():
time.sleep(3)
print("函数运行完毕")
test = timmer(test) #返回是wrapper地址
test() #执行的是wrapper()
③ : 语法糖
将②步骤,修改成语法糖的形式 ,@timmer
相当于test = timmer(test)
def timmer(func):
def wrapper():
start_time = time.time()
func()#运行test
stop_time = time.time()
print("运行时间" + str(stop_time - start_time))
return wrapper
@timmer #test = timmer(test)
def test():
time.sleep(3)
print("函数运行完毕")
#语法糖 @timer就相当于 test = timmer(test)
test()
④ : 增加返回值
在③ 的基础上,添加了返回值.使得函数有返回值
def timmer(func):
def wrapper():
start_time = time.time()
res = func()#运行test
stop_time = time.time()
print("运行时间" + str(stop_time - start_time))
return res
return wrapper
@timmer #test = timmer(test)
def test():
time.sleep(3)
print("函数运行完毕")
return "我是test"
res = test()
print(res)
⑤ : 增加参数
在④的基础上增加参数,使得函数能够添加参数
def timmer(func):
def wrapper(*args,**kwargs):
start_time = time.time()
res = func(*args,**kwargs)#运行test
stop_time = time.time()
print("运行时间" + str(stop_time - start_time))
return res
return wrapper
@timmer #test = timmer(test)
def test(name,age):
time.sleep(3)
print("函数运行完毕名字 : %s 年龄 %s" %(name,age) )
return "我是test"
四 : 解压序列
获取列表或元祖可以用解压队列对应的方式
a获取1,b获取2 ,c获取3
a,b,c = (1,2,3)
print(a,b,c)
取出庞大列表的第一项和倒数第一第二项
其中假如想忽略中间的列表,*temp
可以用*_
替换
a,*temp,b,d= [1,2,3,4,5,6,7]
print(a)
print(b)
print(d)
1
6
7
[2, 3, 4, 5]
python交换变量的另类方式
f1 = 1
f2 = 2
f1,f2 = f2,f1
五 : 装饰器添加参数
① 雏形 :
功能 : 模拟一个用户登录的验证功能+session功能
user_list = [
{'name' : 'sisi','password':'123'},
{'name' : 'keke','password':'123'},
{'name' : 'nana','password':'123'},
]
current_dic = {'username' : None,'login':False}
def auth_func(func):
def wrapper(*args,**kwargs):
if current_dic['username'] and current_dic['login']:
res = func(*args, **kwargs)
return res
username = input('用户名 :').strip()
password = input('密码 :').strip()
for dic in user_list:
if username == dic['name'] and password == dic['password']:
current_dic['username'] = username
current_dic['login'] = True
res = func(*args, **kwargs)
return res
else:
print('用户名密码错误')
return wrapper
@auth_func
def index():
print("京东主页")
@auth_func
def home(name):
print(name+"欢迎回家")
@auth_func
def shopping_car(name):
print("%s的橘子" %name)
index()
home('雪芙')
shopping_car("思思")
② 终极 :
在①中,我们不能选择数据库,所以我们要为装饰器添加一个参数来,让其有选择数据库的功能,所以在①的基础上,外面又嵌套了一层.
@auth(auth_type='filedb')
把@后面看成一个执行的函数返回值是 auth_func
其本质还是 @auth_func
, 只不过,运行调用一次auth(auth_type='filedb')
我们可以在其中做相应的业务逻辑
user_list = [
{'name' : 'sisi','password':'123'},
{'name' : 'keke','password':'123'},
{'name' : 'nana','password':'123'},
]
current_dic = {'username' : None,'login':False}
def auth(auth_type = 'filedb'):
def auth_func(func):
def wrapper(*args,**kwargs):
print(auth_type)
if auth_type == "filedb":
if current_dic['username'] and current_dic['login']:
res = func(*args, **kwargs)
return res
username = input('用户名 :').strip()
password = input('密码 :').strip()
for dic in user_list:
if username == dic['name'] and password == dic['password']:
current_dic['username'] = username
current_dic['login'] = True
res = func(*args, **kwargs)
return res
else:
print('用户名密码错误')
elif auth_type == 'ladp':
print('岑岑')
else:
print("其他方式")
return wrapper
return auth_func
@auth(auth_type='filedb')
def index():
print("京东主页")
@auth(auth_type='ladp')
def home(name):
print(name+"欢迎回家")
@auth(auth_type='xxx')
def shopping_car(name):
print("%s的橘子" %name)
index()
home('雪芙')
shopping_car("思思")