一. 经典的两层装饰器,也是标准装饰器

案例

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)

第二阶

获取认证信息途径有

1. ldap
2. mysql
3. 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)

二. 迭代器

简述:

迭代是一个重复的过程,每一次重复都是基于上一次的结果而来的
注意:迭代不是单纯的重复 迭代器是一种迭代取值的工具,这种取值方式是通用,不依赖于索引
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

迭代对象和迭代器对象区分

迭代的对象:有__iter__内置方法的对象都是可迭代的对象,str、list、tuple、dict、set、文件对象
ps:可迭代对象.__iter__()返回的是迭代器对象 迭代器对象:
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)
二、for循环的工作原理=》迭代器循环
d = {"k1": 111, "k2": 222, "k3": 3333}

for k in d:
print(k)

解释:

for循环的工作步骤
1、调用in后的对象的__iter__方法,得到对应的迭代器
2、k=next(迭代器),然后执行一次循环
3、循环往复,知道把迭代器的值取干净了,抛出异常,for循环会自动捕捉异常,结束循环 迭代器总结:
优点
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))
 

最新文章

  1. authorization配置
  2. ios CoreData NSManagedObject 生命周期
  3. fork()详解
  4. POJ 1062 昂贵的聘礼 (最短路)
  5. 操作系统之进程篇(4)--经典进程间通信(IPC)问题
  6. Oracle11g - dos 命令 sqlplus/nolog 提示 不是内部命令解决办法
  7. 制作手机浏览器显示格式的HTML页面
  8. Mysql的Debug模式实现
  9. Java乔晓松-android中上传图片到服务器Tomcat(Struts2)
  10. ASP.NET农历时间显示(两)
  11. AngularJS简单例子
  12. 【BZOJ5469】[FJOI2018]领导集团问题(动态规划,线段树合并)
  13. C#实现之(自动更新)
  14. animation过渡效果
  15. Java如何显示不同语言的时间?
  16. UVA-10020 Minimal coverage(贪心)
  17. 注册COM
  18. [转]wait,notify,notifyAll,join,yield,sleep的区别和联系
  19. OpenLTE安装教程
  20. JavaScript---循环与闭包

热门文章

  1. 使用WPF实现的 喜马拉雅FM 资源下载工具
  2. 小师妹学JavaIO之:Buffer和Buff
  3. 2、react-生命周期1※※※
  4. win32 socket http 操作
  5. Largest Rectangle in a Histogram【单调栈模板】
  6. yaml读取封装
  7. 【Spring注解驱动开发】面试官:如何将Service注入到Servlet中?朋友又栽了!!
  8. 使用python,pytorch求海森Hessian矩阵
  9. 果然学习好是有道理的,学习Mysql与正则表达式笔记
  10. user is not in the sudoers file