p78-p80
装饰器
- 开放封闭原则
- 在不改变原函数以及代码调用方式的前提下,为其额外增加新的功能
import time
def func1():
time.sleep(3)
def test(func):
start_time = time.time()
func()
end_time=time.time()
print(end_time-start_time)
test(func1) #这里改变了原函数的调用方式了,原先是函数名直接加括号,现在是函数名作为参数传到test函数
- 就要用闭包
import time #改进一下
def func():
time.sleep(3)
def test(func):
def inner():
start_time = time.time()
func()
end_time=time.time()
print(end_time-start_time)
return inner
ret = test(func) #ret 得到inner函数
ret() #相当于inner()
- 再改进
import time
def func1():
time.sleep(3)
def test(func):
def inner():
start_time = time.time()
func()
end_time=time.time()
print(end_time-start_time)
return inner
func1 = test(func1) #这里还用原函数名 func
func1()
- 再改进 标准版
import time
def test(func):
def inner():
start_time = time.time()
func()
end_time=time.time()
print(end_time-start_time)
return inner
@test #装饰器 关键词函数前面加@
def func1():
time.sleep(3)
func1()
- 如果 func1 有返回值呢?
import time
def test(func):
def inner():
start_time = time.time()
func()
end_time=time.time()
print(end_time-start_time)
return inner
@test #装饰器 关键词函数前面加@
def func1():
time.sleep(0.6)
print('func1')
return 1
a = func1()
print(a) # 为啥我得到的是 None,因为最后执行的func1 函数实际是 inner函数,inner默认返回 None
- 改进一下
import time
def test(func):
def inner():
start_time = time.time()
a=func() #这里定义一个返回值给inner函数,最后返回出去
end_time=time.time()
print(end_time-start_time)
return a #返回被装饰的函数的返回值
return inner
@test #装饰器 关键词函数前面加@
def func1():
time.sleep(0.6)
print('func1')
return 111
a = func1()
print(a)
- 如果被装饰函数 func1 有参数呢
import time
def test(func):
def inner(args): #func1 其实就是inner ,所以inner 还要加参数
start_time = time.time()
a=func(args)
end_time=time.time()
print(end_time-start_time)
return a
return inner
@test #装饰器 关键词函数前面加@
def func1(arg1):
time.sleep(0.6)
print('func1')
return 111
a = func1(5)
print(a) #return 111
- 如果不确定有多少个参数呢
import time
def test(func):
def inner(*args,**kwargs):
start_time = time.time()
a=func(*args,**kwargs) #涵盖所有函数的参数,*的打散和聚合 一个*存位置参数,两个存可迭代参数
end_time=time.time()
print(end_time-start_time)
return a
return inner #这个就是标准装饰器
@test #装饰器 关键词函数前面加@
def func1(a): #一个参数
time.sleep(0.6)
print('func1')
return 111
@test
def calc(a,b): #2个参数
time.sleep(0.5)
return a+b
print(calc(5,6))
- 总结
#装饰器的结构如下
def wrapper(f): #wrapper 是装饰器名称,f是被装饰的函数
def inner(*args,**kwargs):
#这里是执行被装饰函数前,增加的额外功能
ret = f(*args,**kwargs)
#这里是执行被装饰函数后,增加的额外功能
return ret
return inner
#用控制台方式模拟登陆网站访问功能,待完善
'''
1、进入控制台主程序,显示所有功能列表
1、登陆
2、注册
3、访问个人主页(需要装饰器验证登陆状态,没有登陆,就讯运行登陆功能)简单显示一句话,再回到循环
4、访问文章列表(需要装饰器验证登陆状态)
5、访问评论列表(需要装饰器验证登陆状态)
2、按q或Q退出
'''
#存放网站功能列表
dict1 = [
{'num':1,'content':'登陆','func':'login'},
{'num':2,'content':'注册','func':'register'},
{'num':3,'content':'访问个人主页','func':'user_info'},
{'num':4,'content':'访问文章列表','func':'user_article'},
{'num':5,'content':'访问评论列表','func':'user_comment'}
]
#存放登陆账号密码
dict2 = [
{'name':'tom','pwd':'123456'},
{'name':'jerry','pwd':'111111'},
]
dict3 = {'login_flag':False} #存放当前登陆账号状态
#装饰器
def test_login(f):
def inner(*args,**kwargs):
if dict3['login_flag']==False:
if login()==False:return
ret = f(*args,**kwargs)
return ret
return inner
#login
def login():
c = 0
while c < 3:
c += 1
name = input('Entry a name:')
pwd = input('Entry a password:')
for i in dict2:
if name == i['name'] and pwd == i['pwd']:
print('成功')
dict3['login_flag']=True
return
else:
continue
return False
#register
def register():
return True
#访问个人主页
@test_login
def user_info():
print('我的主页')
#访问文章列表
@test_login
def user_article():
print('我的文章列表')
return True
#访问评论列表
@test_login
def user_comment():
print('我的评论列表')
def main():
while 1:
for m in dict1:
print(str(m['num'])+'.'+m['content'])
num = input('请选择:')
if num.upper()=='Q' :
break
elif num == '1':
a = login()
if a == False :
print('超过3次')
break
elif num == '2':register()
elif num == '3':user_info()
elif num == '4':user_article()
elif num == '5':user_comment()
else:
continue
main()