函数——嵌套三层函数的装饰器,迭代器
一、嵌套三层函数的装饰器
#分析
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)"的
返回值必须是一个函数的内存地址
#示范一:
def outter(func):
def wrapper(*args, **kwargs):
inp_name=input("please input your name: ").strip()
inp_pwd=input("please input your password: ").strip()
with open('user.db',mode='rt',encoding='utf-8') as f:
for line in f:
name_db,pwd_db=line.strip('\n').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)
#示范二(完善):
# ldap
# mysql
# file
def outter2(mode):
def outter(func):
def wrapper(*args, **kwargs):
inp_name=input("please input your name: ").strip()
inp_pwd=input("please input your password: ").strip()
if mode == "file":
print('认证来源=====>file')
with open('user.db',mode='rt',encoding='utf-8') as f:
for line in f:
name_db,pwd_db=line.strip('\n').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
outter=outter2(mode="mysql")
@outter # index=outter(index) ==>index=wrapper
def index(x, y):
print('index===>', x, y)
index(1, 2) # wrapper(1,2)
#示范三(改进):
def outter2(mode):
def outter(func):
def wrapper(*args, **kwargs):
inp_name=input("please input your name: ").strip()
inp_pwd=input("please input your password: ").strip()
if mode == "file":
print('认证来源=====>file')
with open('user.db', mode='rt', encoding='utf-8') as f:
for line in f:
name_db,pwd_db=line.strip('\n').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)
有参装饰器(三层装饰器)模板!!!
def outter2(x,y,z): def outter1(func): def wrapper(*args ,**kwargs): res =func(*args ,**kwargs) return res return wrapper return outter1 @outter2(1,2,3) # index=outter1(index) def index(): pass index() # wrapper() index() # wrapper()
二、迭代器
1、迭代器
迭代是一个重复的过程,每一次重复都是基于上一次的结果而来的
注意:迭代不是单纯的重复
迭代器是一种迭代取值的工具,这种取值方式是通用,不依赖于索引
基于同一个迭代器取值,取干净了就再也没有了
str ===》索引
list ===》索引
tuple ===》索引
t = (1111, 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, 222, 333, 444, 555, 666)
d = {"k1": 111, "k2": 222, "k3": 3333}
s1 = {'a', 'b', 'c'}
f = open(r'user.db', 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": 3333}
iter_d = iter(d)
while True:
try:
print(next(iter_d))
except StopIteration:
break
2、可迭代对象:有__iter__内置方法的对象都是可迭代的对象,str、list、tuple、dict、set、文件对象
ps:可迭代对象.__iter__()返回的是迭代器对象
3、迭代器对象:
1、有__next__方法
2、有__iter__方法,调用迭代器的__iter__方法得到的就是迭代器自己
ps:迭代器对象之所内置__iter__方法是为了符合for循环的工作步骤
f = open(r'user.db', 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": 3333}
res=d.__iter__()
print(res)
print(res.__iter__())
print(res.__iter__() is res)
print(res.__iter__().__iter__().__iter__() is res)
4、for循环的工作原理=》迭代器循环
for循环的工作步骤:
(1)调用in后的对象的__iter__方法,得到对应的迭代器
(2)k=next(迭代器),然后执行一次循环
(3)循环往复,直到把迭代器的值取干净了,抛出异常,for循环会自动捕捉异常,结束循环
d = {"k1": 111, "k2": 222, "k3": 3333}
for k in d:
print(k)
5、总结迭代器:
优点:
1、不依赖索引,是一种通用的取值方式
2、节省内存
d = {"k1": 111, "k2": 222, "k3": 3333}
iter_d=iter(d)
next(iter_d)
缺点:
1、不能取指定位置的值
2、不能预估值的个数,无法统计长度
ll = [111, 222, 333]
print(ll[2])
iter_ll=iter(ll)
next(iter_ll)
next(iter_ll)
print(next(iter_ll))