一.嵌套三层函数的装饰器(有参装饰器)
案例:
import time
def outter1(func):
def wrapper(*args,**kwargs):
start = time.time()
res=func(*args,**kwargs)
stop = time.time()
print(stop-start)
return res
return wrapper
# @函数的内存地址1(1,2,3,4,5) # 函数的内存地址(index)
def index(x,y):
print('index===>',x,y)
@outter1
def home(name):
print('home====>',name)
引出两个点:
1.可以通过闭包的方式为函数体传参,可以包一层,也可以包两层
2.@后面跟的必须是一个函数的内存地址
@函数的内存地址(1,2,3)是可以的,但是前提是调用函数'函数的内存地址(1,2,3)'的返回值必须是一个函数的内存地址
示范1:
无参装饰器
def outter(func):
def wrapper(*args,**kwargs):
inp_name=input('your name==>').strip()
inp_pwd=input('your password==>').strip()
with open('user.txt','rt',encoding='utf-8')as f:
for line in f:
name_db,pwd_db=line.strip().split(":")
if inp_name == name_db and inp_pwd == pwd_db:
print('login successful')
res = func(*args,**kwargs)
return res
else:
print('账号或密码错误')
return wrapper
@outter
def index(x,y):
print('index==>',x,y)
index(1,2)
示范2:
有参装饰器(仍需改进)
# ldap
# mysql
# file
def outter2(mode):
def outter(func):
def wrapper(*args,**kwargs):
inp_name=input('your name==>').strip()
inp_pwd=input('your pwd==>').strip()
if mode == 'file':
print('认证来源===>file')
with open('user.txt','rt',encoding='utf-8')as f:
for line in f:
name_db,pwd_db=line.strip().split(":")
if inp_name == name_db and inp_pwd:
print('login successful')
res = func(*args,**kwrgs)
return res
else:
print("账号或密码错误")
elif mode == 'ldap':
print('认证来源===>ldap')
elif mode == 'mysql':
print('认证来源===>mysql')
else:
print('未知的认证来源')
return wrapper
return outter
outter=outter2(mode='mysql')
@outter # index=outter(index) ==> index=wrapper
def index(x,y):
print('index===>',x,y)
index(1,2) # wrapper(1,2)
示范3:
改正后的有参装饰器
def outter2(mode):
def outter(func):
def wrapper(*args,**kwargs):
inp_name=input('your name==>').strip()
inp_pwd=input('your password==>').strip()
if mode == 'file':
print('认证来源==>file')
with open('user.txt','rt',encoding='utf-8')as f:
for line in f:
name_db,pwd_db=line.strip().split(":")
if inp_name == name_db and inp_pwd == pwd_db:
print('login successful')
res = func(*args,**kwargs)
return res
else:
print('账号或密码错误')
elif mode == 'ldap':
print('认证来源==>ldap')
elif mode == 'mysql':
print('认证来源==>mysql')
else:
print('未知的认证来源')
return wrapper
return outter
@outter2(mode='mysql') # index=outter(index) ==>index=wrapper
def index(x,y):
print('index===>',x,y)
index(1,2) # wrapper(1,2)
二.迭代器
1.什么是迭代器?
迭代是一个重复的过程,每一次重复都是基于上一次的结果而来的
注意:迭代不是单纯的重复迭代器是一种迭代取值的工具,这种取值方式是通用,不依赖于索引
str === > 索引
list === > 索引
tuple === > 索引
t = (111,222,333,444,555,666)
i = 0
while i < len(t):
print(t[i])
i+=1
dict === > key
set === > 既没有key也没有索引
f 文件对象 == > 既没有key也没有索引
python 为上述类型都内置了__iter__方法
s = 'hello'
ll = [111,222,333]
t = (1111,2222,3333,4444,5555)
d = {'k1':111,'k2':222,'k3':333}
s1 = {'a','b','c'}
f = open(r'user.txt',mode='rt',encoding='utf-8')
f.close()
# 调用 __iter__方法得到的返回值就是对应的迭代器
res = d.__iter__() # res = iter(d)
print(res) # res 是迭代器
a = res.__next__() # a=next(res)
b = res.__next__() # b=next(res)
c = res.__next__() # c=next(res)
#d = res.__next__() # stopiteration
print(c)
d = {'k1':111,'k2':222,'k3':333}
iter_d = iter(d)
while True:
try:
print(next(iter_d))
except StopIteration:
break
可迭代的对象:有__iter__内置方法的对象都是可迭代的对象,str,list,tuple,dict,set,文件对象
ps: 可迭代对象.iter()返回的是迭代器对象
迭代器对象:
1.有__next__方法
2.有__iter__方法,调用迭代器的__iter__方法得到的就是迭代器自己
ps: 迭代器对象之所内置__iter__方法是为了符合for循环第一个工作步骤
f = open(r'user.txt',mode='rt',encoding='utf-8')
line = f.__next__()
print(line)
line = f.__next__()
print(line)
for line in f:
print(line)
f.close()
# line = f.__next__() # 报错
d = {'k1':111,'k2':222,'k3':333}
res = d.__iter__()
print(res) #<dict_keyiterator object at 0x000002BDA81EE590>
print(res.__iter__()) #<dict_keyiterator object at 0x000002BDA81EE590>
print(res.__iter__() is res) #True
print(res.__iter__().__iter__().__iter__() is res) #True
2.for循环的工作原理=> 迭代器循环
d = {'k1':111,'k2':222,'k3':333}
for k in d:
print(k)
for 循环的工作步骤
1.调用in后的对象的__iter__方法,得到对应的迭代器
2.k = next(迭代器),然后执行一次循环
3.循环往复,直到把迭代器的值取干净了,抛出异常,for循环会自动捕捉异常,
结束循环
3.总结迭代器:
优点:
1.不依赖索引,是一种通用的取值方式
2.节省内存
d = {'k1':111,'k2':222,'k3':333}
iter_d = iter(d)
print(next(iter_d))
缺点:
1.不能取指定位置的值
ll = [111,222,333]
print(ll[2]) # 333
iter_ll=iter(ll)
next(iter_ll)
next(iter_ll)
print(next(iter_ll)) # 333
2.不能预估值的个数,无法统计长度