第九篇 装饰器
http://www.cnblogs.com/linhaifeng/articles/6140395.html
复习
age=10
res=True if age > 10 else False #三元表达式
l=['a' for i in range(10)]
g_l=('a' for i in range(10)) #生成器表达式
def test():
for i in range(4):
yield i #是用时候,生成器只能历遍一次哦
t=test() #这里面没有值,生成器取值是执行一个next才会有一个yield输出
# 不执行的话就不产生值
print(t) #<generator object test at 0x00000000028E8150>
print(list(t)) # [0, 1, 2, 3]
for i in t: #0 1 2 3 给在了t内, 遍历t
print(i)
t1=(i for i in t) #生成器t1 表达式 = 历遍生成器t
# 前边不能有print(list(t))或者for i in t: 遍历t会导致输出t1没有了空了,输出[]
print(t1) #<generator object <genexpr> at 0x00000000025D81A8>
print(list(t1)) # 遍历生成器t1内并且以list形式打印[0, 1, 2, 3] ???
# 这不是和print(list(t)) 一样吗,为什么要多余变成t1呢
t1=(i for i in t) #生成器取值是执行一个next才会有一个yield输出
# 不执行的话就不产生值,生成器只能走一次,不能倒着走
# t1,t2里面都没有值,只有next才遍历里面的值
t2=(i for i in t1)
print(list(t1)) #这里把t1的值取空了, t2 就没了
print(list(t2))
输出 生成器只能历遍一次哦
[0, 1, 2, 3]
[]
第九篇 装饰器
本质是函数
http://www.cnblogs.com/linhaifeng/articles/6140395.html
装饰器定义:本质就是函数,功能是为其他函数添加新功能
原则
1.不修改被装饰函数的源代码(开放封闭原则)
2.为被装饰函数添加新功能后,不修改被修饰函数的调用方式
装饰器=高阶函数+函数嵌套+闭包
import time
def cal(l):
start_time=time.time()
res=0
for i in l:
time.sleep(0.1)
res+=i
stop_time = time.time()
print('函数的运行时间是%s' %(stop_time-start_time))
return res
print(cal(range(100))) #输出函数的运行时间是10.06001877784729 4950
# 装饰器定义:本质就是函数,功能是为其他函数添加新功能
# 原则
# 1.不修改被装饰函数的源代码(开放封闭原则)
# 2.为被装饰函数添加新功能后,不修改被修饰函数的调用方式
#
# 装饰器=高阶函数+函数嵌套+闭包
import time
def cal(l):
start_time=time.time()
res=0
for i in l:
time.sleep(0.1)
res+=i
stop_time = time.time()
print('函数的运行时间是%s' %(stop_time-start_time))
return res
print(cal(range(100))) #输出函数的运行时间是10.06001877784729 4950
装饰器预演
import time
def timmer(func):
def wrapper(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs)
stop_time = time.time()
print('函数运行时间是%s' %(stop_time-start_time))
return res
return wrapper
高阶函数
高阶函数定义:
1.函数接收的参数是一个函数名
2.函数的返回值是一个函数名
3.满足上述条件任意一个,都可称之为高阶函数
1.函数接收的参数是一个函数名
import time
def foo():
time.sleep(3)
print('你好啊林师傅')
def test(func):
print(func) #打印输入函数func函数的内存地址
start_time=time.time()
func() #执行
stop_time = time.time()
print('函数运行时间是 %s' % (stop_time-start_time)) #计算func函数的运行时间
test(foo)
输出
<function foo at 0x00000000003F1E18>
你好啊林师傅
函数运行时间是 3.000171422958374
已经能完成,在更改原代码的情况下添加新的功能
但是违反装饰器的原则
2.函数的返回值是一个函数名
def foo():
print('from the foo')
def test(func):
return func
res=test(foo)
# print(res) #函数地址
res() #from the foo
foo=test(foo) #赋值(地址)的参数名和输入一样,
执行foo函数也是foo(),实现装饰器不改变函数使用方式
# # print(res)
foo()
import time
def foo():
time.sleep(3)
print('来自foo')
不修改foo源代码
不修改foo调用方式
多运行了一次foo,不合格
def timer(func):
start_time=time.time()
func()
stop_time = time.time()
print('函数运行时间是 %s' % (stop_time-start_time))
return func #调用func,输出func,然后赋值给同函数名foo,
# foo源代码,调用方式都不变,但是可以添加foo的功能
foo=timer(foo) #多运行了一步func,后return func又运行一次
foo()
函数嵌套
嵌套 在函数内定义另一个函数,
递归 在函数内调用自己
def bar():
print('from bar')
def foo():
print('from foo')
def test():
pass
def father(auth_type): #函数嵌套 ,一层是一个包的层级信息 包:一层套一层,类似箱子套箱子 闭:封装变量 ,当层变量+(函数即变量)
# print('from father %s' %name)
def son():
name='linhaifeng_1'
print('我的爸爸是%s' %name) #当层的局部变量没有,往上一层找
def grandson():
print('我的爷爷是%s' %auth_type)
grandson()
print(locals()) #打印当前层的局部变量 {'son': <function father.<locals>.son at 0x00000000022788C8>, 'auth_type': 'filedb'}
son()
father('filedb')
输出
{'son': <function father.<locals>.son at 0x00000000028F88C8>, 'auth_type': 'filedb'}
我的爸爸是linhaifeng_1
我的爷爷是filedb
装饰器的实现
import time
def timmer(func): #func=test
def wrapper():
# print(func)
start_time=time.time()
func() #就是在运行test()
stop_time = time.time()
print('运行时间是%s' %(stop_time-start_time))
return wrapper
@timmer #test=timmer(test)
def test():
time.sleep(3)
print('test函数运行完毕')
test()
# res=timmer(test) #返回的是wrapper的地址
# res() #执行的是wrapper()
# test=timmer(test) #返回的是wrapper的地址
# test() #执行的是wrapper()
# @timmer 就相当于 test=timmer(test)
装饰器的预演
import time
def timmer(func):
def wrapper(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs)
stop_time = time.time()
print('函数运行时间是%s' %(stop_time-start_time))
return res
return wrapper
加上返回值
import time
def timmer(func): #func=test
def wrapper():
start_time=time.time()
res=func() #就是在运行test()
stop_time = time.time()
print('运行时间是%s' %(stop_time-start_time))
return res #func的返回值
return wrapper
@timmer #test=timmer(test)
def test():
time.sleep(3)
print('test函数运行完毕')
return '这是test的返回值'
res=test() #就是在运行wrapper
print(res)
加上参数
#这里变化还是一步步的变化
import time
def timmer(func): #func=test1
def wrapper(*args,**kwargs): #test('linhaifeng',age=18) args=('linhaifeng') kwargs={'age':18}
start_time=time.time()
res=func(*args,**kwargs) #就是在运行test() func(*('linhaifeng'),**{'age':18})
stop_time = time.time()
print('运行时间是%s' %(stop_time-start_time))
return res
return wrapper
@timmer #test=timmer(test)
def test(name,age):
time.sleep(3)
print('test函数运行完毕,名字是【%s】 年龄是【%s】' %(name,age))
return '这是test的返回值'
@timmer
def test1(name,age,gender):
time.sleep(1)
print('test1函数运行完毕,名字是【%s】 年龄是【%s】 性别【%s】' %(name,age,gender))
return '这是test的返回值'
res=test('linhaifeng',age=18) #就是在运行wrapper
print(res)
#
test函数运行完毕,名字是【linhaifeng】 年龄是【18】
运行时间是3.0040435791015625
这是test的返回值 #运是test的返回值,为什么啊
test1('alex',18,'male')# 这几个值都是给了args
test1函数运行完毕,名字是【alex】 年龄是【18】 性别【male】
def test2(name,age,gender): #test2(*('alex',18,'male','x','y'),**{})
#name,age,gender=('alex',18,'male','x','y')
print(name)
print(age)
print(gender)
#
def test1(*args,**kwargs):
test2(*args,**kwargs) #args=('alex',18,'male','x','y') kwargs={}
# test2('alex',18,gender='male')
test1('alex',18,'male')
解压序列
a,b,c =(1,2,3)
l=[1,2,3,5,6,8,9,5,8,6,8]
a,*_,c=l
print(a,c,_) #1 8 [2, 3, 5, 6, 8, 9, 5, 8, 6] 取l第一个和最后一个 中间的放给 _
a,b,*m,c,d=l
print(a,b,m,c,d) # 1 2 [3, 5, 6, 8, 9, 5, 8] 6 8
带登录验证功能的装饰器
这里是无参数的装饰器 这章节较晕,可以debug看看
user_list=[
{'name':'alex','passwd':'123'},
{'name':'linhaifeng','passwd':'123'},
{'name':'wupeiqi','passwd':'123'},
{'name':'yuanhao','passwd':'123'},
] #如果账户密码是在文件里边,可以用之前学的提取文件内容的方式,要注意文件内的都是字符串,要用eval函数转换成对应的字典或者其他形式
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() #否则输入用户名和密码
passwd=input('密码:').strip()
for user_dic in user_list: #判断用户名和密码是否在user_list内,历遍数据是否对应上
if username == user_dic['name'] and passwd == user_dic['passwd']: #如果用户名和密码都正确了
current_dic['username']=username #把登录用户和是否登录的状态也改掉
current_dic['login']=True
res = func(*args, **kwargs) #执行输入函数
return res
else: #else位置与for相对,整个for循环都没有找到对应的用户名和密码,for内找到的话return就已经停止了,对输出无影响
print('用户名或者密码错误')
print(current_dic['login'])
#这里不应该是赋值给current_dic['login']=False 吗,不然如果上一次登录成功会导致一直是True
#****但是注意这里的current_dic['login']是局部变量,不能影响全局变量内,只能在这个函数内改变,但是不能改变全局变量的current_dic['login']
return wrapper
@auth_func
def index():
print('欢迎来到京东主页')
@auth_func
def home(name):
print('欢迎回家%s' %name)
@auth_func
def shopping_car(name):
print('%s的购物车里有[%s,%s,%s]' %(name,'奶茶','妹妹','娃娃'))
print('before-->',current_dic)
index()
print('after--->',current_dic)
home('产品经理')
输出
before--> {'username': None, 'login': False}
用户名:alex #先登录
密码:123
欢迎来到京东主页 #验证了已经是登录状态,和正确登录,运行函数
after---> {'username': 'alex', 'login': True}
欢迎回家产品经理 #执行home函数
# shopping_car('产品经理')
带参数有验证功能的装饰器
user_list=[
{'name':'alex','passwd':'123'},
{'name':'linhaifeng','passwd':'123'},
{'name':'wupeiqi','passwd':'123'},
{'name':'yuanhao','passwd':'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()
passwd=input('密码:').strip()
for user_dic in user_list:
if username == user_dic['name'] and passwd == user_dic['passwd']:
current_dic['username']=username
current_dic['login']=True
res = func(*args, **kwargs)
return res
else:
print('用户名或者密码错误')
elif auth_type == 'ldap':
print('鬼才特么会玩')
res = func(*args, **kwargs)
return res
else:
print('鬼才知道你用的什么认证方式')
res = func(*args, **kwargs)
return res
return wrapper
return auth_func
@auth(auth_type='filedb') #auth_func=auth(auth_type='filedb')-->@auth_func 附加了一个auth_type --->index=auth_func(index)
def index():
print('欢迎来到京东主页')
@auth(auth_type='ldap')
def home(name):
print('欢迎回家%s' %name)
#
@auth(auth_type='sssssss')
def shopping_car(name):
print('%s的购物车里有[%s,%s,%s]' %(name,'奶茶','妹妹','娃娃'))
print('before-->',current_dic)
index()
print('after--->',current_dic)
home('产品经理')
输出
before--> {'username': None, 'login': False}
认证类型是 filedb
用户名:alex
密码:123
欢迎来到京东主页
after---> {'username': 'alex', 'login': True}
认证类型是 ldap
鬼才特么会玩
欢迎回家产品经理
# shopping_car('产品经理')