迭代的概念
使用for循环遍历取值的过程叫做迭代,比如:使用for循环遍历列表获取值的过程
# Python 中的迭代
for value in [2, 3, 4]:
print(value)
复制代码
1.2 可迭代对象
标准概念:在类里面定义
__iter__
方法,并使用该类创建的对象就是可迭代对象简单记忆:使用for循环遍历取值的对象叫做可迭代对象, 比如:列表、元组、字典、集合、range、字符串
# 常见的可迭代对象
iterables = [
"123", # 字符串
[1,2,3], # 列表
(1,2,3), # 元组
{1:'a',2:'b'}, # 字典
{1,2,3} # 集合
]
可迭代对象之间共同的特点
利用python的内省能力 使用dir()函数获取python对象的属性
# 常见的可迭代对象
iterables = [
"123", # 字符串
[1,2,3], # 列表
(1,2,3), # 元组
{1:'a',2:'b'}, # 字典
{1,2,3} # 集合
]
# for iterable in iterables:
# print(type(iterable))
# for x in iterable:
# print(x,end=',')
# print('')
def common_attrs(*objs):
"""
计算对象之间的共同属性
:param objs:
:return:
"""
assert len(objs) >0
attrs = set(dir(objs[0]))
for obj in objs[1:]:
print(obj)
attrs &= set(dir(obj)) # 取交集
attrs -= set(dir(object)) # 剔除基础对象的属性
return attrs
iterable_common_attrs=common_attrs(*iterables)
print(iterable_common_attrs)
输出结果如下
[1, 2, 3]
(1, 2, 3)
{1: 'a', 2: 'b'}
{1, 2, 3}
{'__contains__', '__iter__', '__len__'}
因为上面都是容器类型的可迭代对象,所以有长度 和是否包含属性
在加入文件类型的可以
f = open('D:\\PycharmProject\\StudentSenior\\file\\demo1.xlsx','r')
# d=common_attrs(f)
iterable_common_attrs &= set(dir(f))
print(iterable_common_attrs)
输出结果如下
{'__iter__'}
现在我们得到可迭代对象的一个唯一接口 __iter__
这种双下划线的__iter__ 方法 我们需要用相应的内置函数去调用 iter()
for iterable in iterables:
print(iter(iterable))
输出如下
<str_iterator object at 0x00000184F4C81F70>
<list_iterator object at 0x00000184F4C81F70>
<tuple_iterator object at 0x00000184F4C81F70>
<dict_keyiterator object at 0x00000184F4B76400>
<set_iterator object at 0x00000184F4B13940>
<_io.TextIOWrapper name='D:\\PycharmProject\\StudentSenior\\file\\demo1.xlsx' mode='r' encoding='cp936'>
我们会 发现生成了iterator object对象,这也是 迭代器
迭代器共同的属性
# 由可迭代对象列表得到相应的迭代器列表
iterator = [iter(iterable) for iterable in iterables]
# 计算迭代器的共同属性
iterator_common_attrs = common_attrs(*iterator)
print(iterator_common_attrs)
输入结果如下
{'__iter__', '__next__'}
证明迭代器有两个接口 __iter__ 和 __next__
对一个迭代器迭代
actions = ['点赞','投币','收藏'] # 可迭代对象
actions_iterator = iter(actions) # 构建迭代器
while 1:
action = next(actions_iterator) # 运行三次
print(action)
结果如下:
Traceback (most recent call last):
File "D:\PycharmProject\StudentSenior\test_openpyxl\test05.py", line 8, in <module>
action = next(actions_iterator) # 运行三次
StopIteration
点赞
投币
收藏
我们可以发现 在迭代完最后一个元素后在去迭代 发生了一个异常StopIteration,也就是迭代终止的意思
至此我们已经知道了迭代的三个关键步骤:
调用iter(iterable)来构建迭代器
(多次)调用next(iterator)来获取值
最后捕获StopIteration异常来判断迭代结束
改进如下
# 用while 循环模拟for循环迭代
# 创建迭代器
iterator = iter(actions) # 对应 可迭代对象的__iterator__ 方法
while 1:
try:
# 通过迭代器获取下一个对象
print(next(iterator)) # 对应迭代器的 __next__ 方法
except StopIteration: # 捕获异常来判断结束
# 迭代结束
break
迭代器的 __iter__ 方法作用在哪里呢?
自定义一个迭代器
迭代器的的基本功能:
初始化时要传入可迭代对象,这样才能知道去那取数据
要初始化迭代进度
每次迭代时,即每次调用__next__() 方法时:
如果仍有元素可供迭代,则返回本轮迭代的元素,同时更新当前迭代进度
如果已无元素可供返回,则迭代结束,抛出StopIteration异常
再添加一点额外的逻辑:
设置一个黑名单,如果当前元素在黑名单内,则跳过
将某些符合条件的数据*2之后再返回
BLACK_LIST = ['白嫖','取关']
class SuzhiIterator:
def __init__(self,actions):
self.actions =actions
self.index = 0 # 初始化索引下标
def __next__(self):
while self.index < len(self.actions):
action = self.actions[self.index]
self.index +=1
if action in BLACK_LIST:
continue
elif '币' in action:
return action*2
else:
return action
raise StopIteration
actions = ['点赞','投币','取关']
sz_iterator = SuzhiIterator(actions)
while True:
try:
print(next(sz_iterator))
except StopIteration:
break
这个可以放在while 循环里面去 迭代,但是不能放在for 循环去迭代,
会报 是一个不可迭代对象
TypeError: 'SuzhiIterator' object is not iterable
那这时候我们可能想到要不要额外定义一个类 去实现__iter__
# 一个没有存在意义的可迭代对象
class SuzhiActions:
def __init__(self,actions):
self.actions = actions
def __iter__(self):
return SuzhiIterator(self.actions)
for i in SuzhiActions(actions):
print(i)
我们这样做太过于冗余
我们正确的做法是让迭代器自己实现
class SuzhiIterator:
def __init__(self,actions):
self.actions =actions
self.index = 0 # 初始化索引下标
def __next__(self):
while self.index < len(self.actions):
action = self.actions[self.index]
self.index +=1
if action in BLACK_LIST:
continue
elif '币' in action:
return action*2
else:
return action
raise StopIteration
def __iter__(self):
return self
在这里 __iter__ 接口的含义就是要返回一个迭代器,那现在__iter__ 已经在这个迭代器里面了,而他这个对象自己就是一个迭代器,所以返回这个对象就可以了
迭代器协议
在python文档中明确指出了,迭代器必须同时实现 __next__ 和 __iter__ 两个方法,这称之为 迭代器协议
根据这个协议,迭代器必须是可迭代的,换言之,迭代器 是一种 可迭代对象
缺少了 __iter__ 方法的迭代器是不完整的,不符合迭代器协议的要求
所有迭代器的 __iter__ 方法都只要千篇一律的return shlf 即可
标签:__,iterator,迭代,python,self,iter,actions From: https://www.cnblogs.com/niunai/p/16906498.html