一、三者的关系

二、可迭代对象与迭代器
可迭代对象包含迭代器; 若一个对象拥有__iter__方法,则是可迭代对象;若一个对象拥有next方法,则是迭代器; 定义可迭代对象,必须实现__iter__方法;定义迭代器,必须实现__iter__和next方法。可能会发问:结论三与结论二是否有点矛盾?既然一个对象拥有next方法就是迭代器,那为什么迭代器必须同时时间__iter__与next方法? 原因就在于结论一,迭代器也是可迭代对象,因此迭代器必须也实现__iter__方法。
2.1、__iter__()与next()方法
__iter__():该方法返回的是当前对象的迭代器类的实例。因为可迭代对象与迭代器都要实现这个方法,因此有两种写法:写法一:用于可迭代对象类的写法,返回该可迭代对象的迭代器类的实例。写法二:用于迭代器类的写法,直接返回self(即自己本身),表示自身即是自己的迭代器。next():该方法返回迭代的每一步,实现该方法时注意最后超出便捷要抛出StopIteration异常。
2.2、可迭代对象与迭代器定义
class MyList(object): # 定义可迭代对象类
def __init__(self, num):
self.data = num # 上边界
def __iter__(self):
return MyListIterator(self.data) # 返回该可迭代对象的迭代器类的实例
class MyListIterator(object): # 定义迭代器类,其是MyList可迭代对象的迭代器类
def __init__(self, data):
self.data = data # 上边界
self.now = 0 # 当前迭代值,初始为0
def __iter__(self):
return self # 返回该对象的迭代器类的实例;因为自己就是迭代器,所以返回self
def __next__(self): # 迭代器类必须实现的方法,python2中是next(),python3中是__next__()
while self.now < self.data:
self.now += 1
return self.now - 1 # 返回当前迭代值
raise StopIteration # 超出上边界,抛出异常
my_list = MyList(5) # 得到一个可迭代对象
print(type(my_list) ) # 返回该对象的类型
my_list_iter = iter(my_list) # 得到该对象的迭代器实例,iter函数在下面会详细解释
print(type(my_list_iter))
for i in my_list: # 迭代
print(i)
print(type(iter(MyListIterator(1))))
# 结果
<class '__main__.MyList'>
<class '__main__.MyListIterator'>
0
1
2
3
4
<class '__main__.MyListIterator'>
注:iter()是直接调用该对象的__iter__(),并把__iter__()的返回结果作为自己的返回值
三、生成器
3.1、生成器概念
生成器 是种特殊的迭代器,生成器自动实现了“迭代器协议”(即__iter__与next方法),不需要再手动实现两方法。生成器在迭代的过程中可以改变当前迭代值,而修改普通迭代器的当前迭代值往往会发生异常,影响程序的执行。
3.2、生成器定义
def myList(num): # 定义生成器
now = 0 # 当前迭代值,初始为0
while now < num:
val = (yield now) # 返回当前迭代值,并接受可能的send发送值;yield在下面会解释
now = now + 1 if val is None else val # val为None,迭代值自增1,否则重新设定当前迭代值为val
my_list = myList(5) # 得到一个生成器对象
print(my_list.__next__()) # 返回当前迭代值
print(my_list.__next__())
my_list.send(3) # 重新设定当前的迭代值
print(my_list.__next__())
print(dir(my_list)) # 返回该对象所拥有的方法名,可以看到__iter__与next在其中
# 结果
0
1
4
['__class__', '__del__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__name__', '__ne__', '__new__', '__next__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'gi_code', 'gi_frame', 'gi_running', 'gi_yieldfrom', 'send', 'throw']
注:具有yield关键字的函数都是生成器,yield可以理解为return,返回后面的值给调用者。不同的是return返回后函数会释放,而生成器不会,在直接调用next()方法或用for语句进行下一次迭代时,生成器会从yield下一句开始执行,直至遇到下一个yield。
本文深入解析了可迭代对象与迭代器的关系,阐述了如何定义及区分两者,重点介绍了生成器的概念、定义及其动态迭代特性。通过实例演示,展示了如何创建和使用MyList类和生成器myList来说明迭代过程。
1783

被折叠的 条评论
为什么被折叠?



