生成器部分回顾、装饰器、装饰器预演、装饰器实现、加返回值、加参数、加验证功能、带参数验证功能(少用) 第十天 2018.10.24
生成器部分回顾
装饰器、装饰器预演、装饰器实现、加返回值、加参数
装饰器加验证功能、带参数验证功能
生成器部分回顾:
Pythonic:保证代码可读性的前提下,尽可能缩短代码行数
#解压方式11对应 #应用于某种场景 a,b,c='hel' #多一报错少一报错 [0,2,3,6,5,1,8,7,4] a,*d,c=l a=1,c=4,*d=[中间所有] #交换值 a=1,b=2 a,b=b,a
for循环可以直接遍历生成器函数
def test():
for i in range(4):
yield i
t=test()
for i in t:
print(i)
t1=(i for i in t) #---->t1为生成器
print(list(t1))
list() #为空 ---->t1为生成器遍历t,t已经被上面遍历过了,生成器只能被遍历一次
t1=(i for i in t) #---->t1只是一个生成器,生成器只能执行一次
t2=(i for i in t1) #---->t1为生成器里面的东西
print(list(t1)) #遍历t1,t1中的值已经被取空
print(list(t2)) #为空,遍历t1时为遍历空列表
装饰器:本质就是函数,功能是:为其他函数添加附加功能
原则:不修改被修饰函数的源代码;不修改被修饰函数的调用方式
函数加个计算函数执行时间功能
函数源代码和调用方式被修改后,有可能会影响该函数和其他函数之间的执行关系,造成原本功能出问题
import time
def cal(l):
start_time=time.time() #函数开始执行时间
res=0
for i in l:
time.sleep(0.1)
res+=i #计算累加range(100)的结果
stop_time = time.time() #函数结束执行时间
print('函数的运行时间是%s' %(stop_time-start_time))
return res #获得函数的返回值
print(cal(range(100))) #该函数是计算累加,打印cal()函数的返回值
装饰器预演
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
@timmer #装饰器---->个人理解为:给待装饰函数增加一个功能
#cal=timmer(cal) #装饰器作为一个整体函数在变量(待装饰函数)执行后,自身不会变化
#被执行过得变量(待装饰函数)自身也不会发生改变,即被装饰函数自身不变且自身调用方式不变
def cal(l): #原函数功能为计算某个可迭代对象的和
res=0
for i in l:
time.sleep(0.5)
res+=i #可以计算整数类型---->列表,元组,集合
return res
res=cal(range(10))
print(res)
装饰器的知识储备
装饰器=高阶函数+函数嵌套+闭包
高阶函数:函数接收的参数是一个函数名或者函数的返回值是一个函数名
修改了函数的调用方式
接收的参数是一个函数名
import time
def foo():
time.sleep(3)
print('你好啊林师傅')
def test(func):
# print(func) #---->foo()的内存地址
start_time=time.time()
func() #运行foo函数func形参传递的是foo函数
stop_time = time.time()
print('函数运行时间是 %s' % (stop_time-start_time))
# foo() #----->本来foo函数调用方式
test(foo) #----->现在foo函数调用方式,通过test函数调用
同时满足两个高阶函数的条件
def foo():
print('from the foo')
def test(func):
return func
res=test(foo) #test()的运行结果,test的返回值是foo函数
# print(res) #res是foo函数的内存地址
res()
foo=test(foo) #test()的运行结果,test的返回值是foo函数
# # print(foo) #foo是foo函数的内存地址
foo() #不改变函数的调用方式,不修改源代码
#不修改foo源代码
#不修改foo调用方式
import time
def foo():
time.sleep(3)
print('来自foo')
#多运行一次
def timer(func):
start_time=time.time()
func() #运行一次传入函数,从而计算运行一次所需的时间
stop_time = time.time()
print('函数运行时间是 %s' % (stop_time-start_time))
return func #返回值为传入函数
foo=timer(foo) #给原foo函数增加功能,增加的功能为timer()函数的函数体
#但是timer函数中会调用一次foo函数
foo() #不改变函数的调用方式---->调用foo函数
#变成执行foo函数---->执行timer函数(内会单独执行一次foo函数)
#因此foo函数调用方式没改变却会被多调用一次
#没有修改被修饰函数的源代码,也没有修改被修饰函数的调用方式,但是也没有为被修饰函数添加新功能
def timer(func):
start_time=time.time()
return func #函数返回值后面的语句不会被执行
stop_time = time.time() #未执行
print('函数运行时间是 %s' % (stop_time-start_time)) #未执行
foo=timer(foo)
foo()
嵌套函数:函数内部重新定义了另一个函数
print(locals())----->打印当前层的局部变量
func()的局部变量有seven、outer函数的地址(风湿理论--->函数即变量)
def father(auth_type):
# print('from father %s' %name)
def son():
# name='.....'
# print('我的..是%s' %name) #此层没有auth_type则向上找
def grandson():
print('我的...是%s' %auth_type) #此层没有auth_type则向上找
grandson()
# print(locals())
son()
# father('....')
father('filedb')
#每层函数相当于一个包,里层需要的局部变量本包里找不到向上找,上一层找不到继续向上找,以此类推;
#闭---->封装;封装变量
#grandson封装的变量:name son封装的变量:grandson father封装的变量:son、name
#grandson找变量,先找自己包里。son找变量,先在自己包里找,找不到去上一层father包里找
装饰器实现
import time
def timmer(func): # func=test
def wrapper():
# print(func)
start_time = time.time()
func() # 就是在运行test() --->跳回timmer,然后执行test()函数
stop_time = time.time()
print('运行时间是%s' % (stop_time - start_time))
return wrapper #返回test()--->test()收到了wrapper函数的地址
@timmer # test=timmer(test) timmer--->装饰器
#执行函数timmer,将test()传入形参运行,timmer函数执行的结果是wrapper函数的地址
#test收到了wrapper函数的地址
def test():
time.sleep(3)
print('test函数运行完毕')
test() #运行wrapper函数
# 用res改变了函数的调用方式---->原来用test()直接调用
# res=timmer(test) #返回的是wrapper的地址
# res() #执行的是wrapper()
# test=timmer(test) #返回的是wrapper的地址
# test() #执行的是wrapper()
# @timmer 就相当于 test=timmer(test)
# @+装饰器名
加返回值
def timmer(func): # func=test
def wrapper():
# print(func)
start_time = time.time()
res=func() # 就是在运行test()并将test函数返回值赋值给res
stop_time = time.time()
print('运行时间是%s' % (stop_time - start_time))
return res #返回值为res是test函数的返回值;此返回值为wrapper函数的返回值
#用wrapper函数的返回值接收test函数的返回值
return wrapper #此返回值为timmer函数的返回值
@timmer # test=timmer(test) timmer--->装饰器
def test():
time.sleep(3)
print('test函数运行完毕')
return '这是test的返回值'
res=test() #res为test函数的返回值,此处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})
#func()即test(),实参根据闭包向上一级找即wrapper函数的实参
stop_time = time.time()
print('运行时间是%s' %(stop_time-start_time))
return res #为wrapper函数的返回值,此处是构造器所增加函数的传递
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 '这是test1的返回值'
# res=test('linhaifeng',age=18) #就是在运行wrapper
# # print(res)
# test1('alex',18,'male')
test('ALEX',15)
test1('alex',18,'male')
#可以把wrapper函数中的res=和return res返回值都删除。程序执行结果无变化
#只有赋值--->空类型;空类型不需要返回值;所以上面的res赋值只是得到test()函数里面的打印
#上面之所以出现返回值是因为打印了原函数返回值,并不是空类型
加个验证功能的装饰器:
user_list=[
{'name':'alex','passwd':'123'},
{'name':'linhaifeng','passwd':'123'},
{'name':'wupeiqi','passwd':'123'},
{'name':'yuanhao','passwd':'123'},
]
current_dic={'username':None,'login':False} #判断是否登录,以及登录状态;登录后才可以执行index()等3个函数
def auth_func(func):
def wrapper(*args,**kwargs):
if current_dic['username'] and current_dic['login']: #如果用户名以及登录状态都True,则...
res = func(*args, **kwargs) #执行func函数
return res #使res有存在的意义,wrapper函数的返回值为res
#登录成功密码正确后后俩函数不用执行wrapper函数下面另外的操作
username=input('用户名:').strip() #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 #改变全局变量current_dic中的,所以if中局部变量调用改变后的全局变量
res = func(*args, **kwargs)
return res
else:
print('用户名或者密码错误')
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函数前,判断登录状态及密码字典里的内容
index()
print('after--->',current_dic) #执行index函数后,判断登录状态及密码字典里的内容
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('❤')
shopping_car('您')
浙公网安备 33010602011771号