装饰器进阶和迭代器
昨日补充
可变类型,直接在函数内部调用
不可变类型,需要在函数内部调用,要使用global
叠加装饰器:
每一个新的功能都应该写一个新的装饰器
需求:
为被装饰对象,添加统计时间与登录认证的功能
# 登录认证
import time
def re_login():
with open('a.txt', 'r', encoding='utf-8') as rf:
data = rf.read()
data1 = data.strip('
').split('|')
data2 = ''.join(data1)
data3 = data2.split('
')
return data3
# print(data3)
# 登录认证装饰器
def login(func):
def inner1(*args, **kwargs):
username = input('请输入用户名:').strip()
password = input("请输入密码:").strip()
res = re_login()
if username + password in res:
print('恭喜您,登录成功!')
re = func(*args, **kwargs)
return re
else:
print('对不起,登录失败!')
re = func(*args, **kwargs)
return re
return inner1
# 统计时间装饰器
def time_record(func):
def inner2(*args, **kwargs):
print('开始统计!')
start_time = time.time()
res = func(*args, **kwargs)
end_time = time.time()
print(f'执行时间:{end_time - start_time}')
return res
return inner2
# @login # inner1=inner(inner2)
# @time_record # inner2
@time_record
@login
def func():
print('开始下载电影!')
time.sleep(5)
print('下载电影结束!')
func()
开始统计!
请输入用户名:godlover
请输入密码:123456
恭喜您,登录成功!
开始下载电影!
下载电影结束!
执行时间:11.740200519561768
什么是叠加装饰器:
在同一个被装饰对象中,添加多个装饰器,并执行
@装饰1
@装饰2
def 被装饰对象():
pass
ps:装饰器在调用被装饰对象时才添加功能
装饰顺序:从下至上
执行顺序:从上至下
编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码
info_dict1 = {
'name_info': None
}
def re_login():
username = input('请输入用户名:').strip()
password = input('请输入密码:').strip()
with open('a.txt', encoding='utf-8') as f:
for line in f:
# print(line)
name, pwd = line.strip('
').split('|')
if username == name and password == pwd:
print('登录成功!')
info_dict1['name_info'] = name
else:
print('登录失败!')
def login(func):
def inner(*args, **kwargs):
if info_dict1.get('name_info'):
print('免密登录成功!')
res = func(*args, **kwargs)
return res
else:
re_login()
return inner
@login
def func1():
print(1)
@login
def func2():
print(2)
@login
def func3():
print(3)
func1()
func2()
func3()
请输入用户名:godlover
请输入密码:123456
登录成功!
登录失败!
免密登录成功!
2
免密登录成功!
3
叠加装饰器的理解
内部的具体运行方式
def wrapper1(func):
def inner1(*args, **kwargs):
print('1-----start')
# 被装饰对象在被调用时,如果还有其他装饰器,则会先执行其他装饰器中的inner
res = func(*args, **kwargs)
print('1-----end')
print(res)
return res
print(1)
return inner1
def wrapper2(func):
def inner2(*args, **kwargs):
print('2-----start')
res = func(*args, **kwargs)
print('2-----end')
print(res)
return res
print(2)
return inner2
def wrapper3(func):
def inner3(*args, **kwargs):
print('3-----start')
res = func(*args, **kwargs)
print('3-----end')
print(res)
return res
print(3)
return inner3
@wrapper1 # 3
@wrapper2 # 2
@wrapper3 # 1
def func():
print('from func')
return 1
func()
3
2
1
1-----start
2-----start
3-----start
from func
3-----end
1
2-----end
1
1-----end
1
ps:
无论inner中出现任何判断,都要返回fun(*args,**kwargs)的结果
当被装饰器对象还有其他装饰器时跳过直接执行inner
无参装饰器:
装饰在被装饰对象时,没有传参数的装饰器
@wrapper
有参装饰器:
@wrapper('参数')
用途:
在某些时候我们需要给用户的权限进行分类
# 调用时@wrapper('参数1')
def user_auth(user_role):
def wrapper(func):
def inner(*args, **kwargs):
if user_role == 'SVIP':
print(1)
res = func(*args, **kwargs)
return res
elif user_role == '普通用户':
print(2)
res = func(*args, **kwargs)
return res
return inner
return wrapper
# @user_auth('SVIP') # 相当于@和后面的分开,先执行函数user_auth,返回wrapper,再将@和wrapper结合起来,返回inner
# def func():
# print('from func')
#
#
# func()
@user_auth('普通用户')
def func():
print('from func')
func()
2
from func
wraps:是一种修复工具,修复地是被装饰对象的空间
例如查看函数内部的注释:
from functools import wraps
def wrapper(func):
@wraps(func) # 是一个修复工具,用来修复被装饰对象的空间
def inner(*args, **kwargs):
'''
这里是inner的注释
:param args:
:param kwargs:
:return:
'''
res = func(*args, **kwargs)
return res
return inner
@wrapper
def func():
'''
这里是func的注释
:return:
'''
print('from func')
print(func.__doc__)
这里是func的注释
:return:
迭代器
迭代器的工具
迭代:指的是重复迭代,每一个迭代的结果都是基于上一次的结果而来的
迭代器:指的是迭代取值的工具
可迭代对象:所有的序列类型:str,list,dict,tuple,set,f
什么是可迭代对象:
凡是内部有_ iter _()方法的都是可迭代对象
什么是迭代器对象:
通过可迭代对象._ iter _()方法的返回值就是迭代器对象
如何迭代取值:
迭代器对象._ next _()
ps:迭代器中的值取完时,会报错StopIteration
list =['jason','sean','egon','tank']
iter_list1 = list._iter_()
while True:
#try:捕获异常
try:
print(iter_list1._next_())#报错
except StopIteration:
break
迭代器的优缺点:
优点:
1.不依赖于索引,迭代取值
2.节省内存空间
缺点:
1.取指定的某个值比较麻烦,每次取值都要从第一个值开始,无法通过索引取值
2.不能够通过len()计算长度
总结
可迭代对象 vs 迭代器对象
获取可迭代对象:
定义序列类型
特点:
凡是内置有_ iter _()方法的都是可迭代对象
获取迭代器对象:
过可迭代对象._ iter _()方法的返回值就是迭代器对象
特点:
内置有_ next _()方法
for 循环的原理
in自动将可迭代对象调用_iter_()方法变成迭代器对象
for i in 可迭代对象:
#迭代器对象调用_next_()方法取值
print(I)
里面也调用捕获异常机制
迭代器对象的本质是一个可迭代对象
文件本质既是可迭代对象又是迭代器对象
文件计较特殊:文件读取出来的时候就是一个迭代器对象
最后注意:
可迭代器对象不一定是迭代器对象(文件既是可迭代对象,也是迭代器对象,但是其他可迭代器不是迭代器对象)
但是迭代器对象一定是可迭代对象