函数三大器之迭代器
1.装饰器补充
1.叠加装饰器
-
装饰的顺序: 由下到上装饰
-
执行的顺序: 由上往下
def wrapper1(func):
def inner1(*args, **kwargs):
print('1---start')
# 被裝飾對象在調用時,如果還有其他裝飾器,會先執行其他裝飾器中的inner
# inner2
res = func(*args, **kwargs)
print('1---end')
return res
return inner1
def wrapper2(func):
def inner2(*args, **kwargs):
print('2---start')
res = func(*args, **kwargs)
print('2---end')
return res
return inner2
def wrapper3(func):
def inner3(*args, **kwargs):
print('3---start')
res = func(*args, **kwargs)
print('3---end')
return res
return inner3
'''
叠加裝飾器的裝飾順序與執行順序:
- 裝飾順序: 调用wrapper装饰器拿到返回值inner
由下往上裝飾
- 執行順序: 调用装饰过后的返回值inner
由上往下執行
'''
2.有参装饰器
# 无参装饰器: 装饰在被装饰对象时,没有传参数的装饰器。
'''
# 以下是无参装饰器
@wrapper1 # inner1 = wrapper1(inner2)
@wrapper2 # inner2 = wrapper2(inner3)
@wrapper3
'''
# 有参装饰器:装饰在被装饰对象时,传参数的装饰器。
# 有参装饰器: 在某些时候,我们需要给用户的权限进行分类
'''
# 以下是有参装饰器
@wrapper1(参数1) # inner1 = wrapper1(inner2)
@wrapper2(参数2) # inner2 = wrapper2(inner3)
@wrapper3(参数3)
'''
# 有参装饰器
def user_auth(user_role): # 'SVIP'
def wrapper(func):
def inner(*args, **kwargs):
if user_role == 'SVIP':
# 添加超级用户的功能
res = func(*args, **kwargs)
return res
elif user_role == '普通用户':
print('普通用户')
# 添加普通用户的功能
res = func(*args, **kwargs)
return res
return inner
return wrapper
# 被装饰对象
# @user_auth('SVIP')
wrapper = user_auth('普通用户')
补充:
'''
wraps: (了解)
是一个修复工具,修复的是被装饰对象的空间。
from functools import wraps
'''
from functools import wraps
def wrapper(func):
# 原来在没有调用wraps前执行index的函数地址是装饰器的地址,在将装饰器inner函数上面添加@wraps(func)可以将调用的函数地址再返回给原函数
2.迭代器
1.什么是迭代器
迭代器就是指迭代取值的工具,迭代就是指重复反馈过程的活动,每一次对过程的重复就是迭代,而每一次迭代的结果会作为下一次迭代的初始值,单纯的重复不是迭代
2.什么是可迭代对象
凡是内部有.__ iter __()方法的都是可迭代对象,比如序列类型为:str, list, tuple, dict ,set, f(打开的文件). 等
str1.__iter__()
list1 = [1, 2, 3] # list([1, 2, 3])
list1.__iter__()
set.__iter__()
dict.__iter__()
tuple.__iter__()
open('a.txt').__iter__()
3.什么是迭代器对象
调用obj.__ iter __()方法返回的结果就是一个迭代器对象(Iterator)
注意:可迭代对象依赖索引取值,迭代器对象不依赖索引取值
# 依赖索引取值
l1 = [1, 2, 3]
n = 0
while n < len(l1):
print(l1[n])
n += 1
# 不依赖索引取值
l1 = [1, 2, 3]
iter_l1 =l1.__iter__()
while True:
print(iter_l1.__next__())
# 当迭代器对象里面的元素被拿就会报错,下面这种方法可以改善
l1 = [1, 2, 3]
iter_l1 =l1.__iter__()
while True:
try: # 通过try捕获异常
print(iter_l1.__next__())
# 立即触发此处代码 StopIteration
except StopIteration:
break
list1 = [1, 2, 3, 4]
for line in list1: # list1是可迭代对象 ----> 内部会自动调用.__iter__() ---> 迭代器对象--->调用try,except stopiteration,brek等完整的拿到全部数据
# 迭代器对象.__next__()
print(line)
# 注意:确定: 迭代器对象也是一个可迭代对象
l1 = [1, 2, 3, 4]
iter_l1 = l1.__iter__()
print(iter_l1.__iter__() is iter_l1)
True
# 可迭代对象不一定是迭代器对象
l1 = [1, 2, 3, 4]
iter_l1 = l1.__iter__()
print(iter_l1 is l1)
False
注意: 唯独文件比较特殊: 因为文件从读取出来的时候就是一个迭代器对象
# f ---> 可迭代对象, 还是迭代器对象
f = open('user.txt', 'r', encoding='utf-8')
# 确定: 文件既是可迭代对象,也是迭代器对象。
# iter_f ---> 迭代器对象
# iter_f = f.__iter__()
print(iter_f is f) # True
4.迭代器对象的优缺点是什么?
优点:1.不依赖于索引迭代取值 2.节省内存空间
缺点:1.取指定某个值麻烦, 每次取值都要从第一个值开始