迭代器
定义
- 当类中定义了__iter__和__next__两个方法
- __iter__方法需要返回对象本身,即:self
- __next__方法,返回下一个数据,如果没有数据了,则需要抛出一个StopIteration的异常。
迭代器类型
#创建迭代器类型
class It():
def __init__(self):
self.counter = 0
def __iter__(self):
return self
def __next__(self):
self.counter += 1
if self.counter == 3:
raise StopIteration
return self.counter
#根据类实例化创建一个迭代器对象
print('创建一个迭代器对象obj1')
obj1 = It()
v1 = next(obj1) # obj1.__next__()
print(v1) # 1
v2 = next(obj1) # obj1.__next__()
print(v2) # 2
#v3 = next(obj1) # obj1.__next__()
#print(v3) # raise StopIteration
print('创建一个迭代器对象obj2')
obj2 = It()
for item in obj2: # 首先执行迭代器对象的__iter__方法获取返回值,一直去反复的执行next(对象),并赋值给item
print(item)
'''
迭代器对象支持通过next取值,如果取值结束则自动抛出StopIteration
for循环内部在循环时,先执行__iter__方法,获取一个迭代器对象,然后不断执行的next取值(有异常StopIteration则终止循环)。
'''
可迭代对象
定义
- 如果一个类中有__iter__方法且返回一个迭代器对象,则我们称以这个==类创建的对象==为==可迭代对象==
- 可迭代对象是可以使用for来进行循坏,在循环内部其实是先执行__iter__方法,获取其迭代器对象,然后再在内部执行这个迭代器对象的next功能,逐步取值。
# 如果一个类中有__iter__方法且返回一个迭代器对象,则我们称以这个类创建的对象为可迭代对象
class Foo():
def __iter__(self):
return 迭代器对象(或者是生成器对象)
obj = Foo() # obj是可迭代对象
# 可迭代对象是可以使用for来进行循坏,在循环内部其实是先执行__iter__方法,获取其迭代器对象,然后再在内部执行这个迭代器对象的next功能,逐步取值。
for item in obj:
pass
一般我们是把可迭代对象和迭代器结合来做的:
#迭代器类 他的实例对象是迭代器对象
class It():
def __init__(self):
self.counter = 0
def __iter__(self):
return self
def __next__(self):
self.counter += 1
if self.counter ==3:
raise StopIteration()
return self.counter
#可迭代类 他的实例对象是一个迭代器对象(也就是返回上面的迭代器类)
class Foo():
def __iter__(self):
return It()
obj1 = Foo()
# for循环都是先调用obj1这个对象的__iter__方法获取一个迭代器对象(It()),然后去执行他的__next__方法
for item in obj1:
print(item)
'''所以,如果直接用for去循环一个迭代器对象,那么
for循环都是先调用迭代器这个对象的__iter__方法获取自己,也就是获取到了迭代器对象,然后去执行自己的__next__方法
例如这样:
obj2 = It()
for item in obj2:
print(item)
'''
实例:range()
- 过程分析
#range()返回的是一个可迭代对象
>>> v1 = range(1000)
#验证这个可迭代对象,查看他的有__iter__方法,没有__next__方法
>>> dir(v1)
['__bool__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index', 'start', 'step', 'stop']
#可迭代对象调用__iter__函数来获取迭代器对象
>>> v2 = v1.__iter__()
#验证这个迭代器对象,查看他的有__iter__方法,也有__next__方法
>>> dir(v2)
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__length_hint__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__']
#然后通过迭代器对象的__next__方法可以获取值
>>> v2.__next__()
0
>>> v2.__next__()
1
>>> v2.__next__()
2
>>> v2.__next__()
3
>>> v2.__next__()
4
#一般我们使用for循环来调用range(),其实也是这样一个过程,首先通过调用__iter__函数来获取迭代器对象,然后通过迭代器对象的__next__方法可以获取值
- 自己实现range
#迭代器类
class IterRange():
def __init__(self,num):
self.num = num
self.counter = -1
def __iter__(self):
return self
def __next__(self):
self.counter += 1
if self.counter == self.num:
raise StopIteration()
return self.counter
#可迭代类
class Myrange():
def __init__(self,max_num):
self.max_num = max_num
def __iter__(self):
return IterRange(self.max_num)
# Myrange(3) 返回的是一个实例对象:可迭代对象
for item in Myrange(3):
print(item)
生成器
定义
如果按照迭代器的规定来看,其实生成器类也是一种特殊的迭代器类(==生成器也是一个特殊的迭代器==)
#创建生成器函数
def func():
'''函数中,只要有yield,那么返回就是一个yield_obj生成器(==generator==)对象,不会执行函数内部的代码'''
yield 1
yield 2
#创建生成器对象(内部是根据生成器类generator创建的对象),生成器类的内部声明了:__ietr__,__next__方法。 所以也符合迭代器的定义,所以生成器是特殊的迭代器
print('创建生成器对象obj1')
obj1 = func()
v1 = next(obj1)
print(v1) # 1
v2 = next(obj1)
print(v2) # 2
# v3 = next(obj1) # StopIteration
# print(v3)
print('创建生成器对象obj2')
obj2 = func()
for item in obj2:
print(item)
实例:range()
#基于可迭代对象&生成器 实现:自定义range
class Myrange():
def __init__(self,max_num):
self.max_num = max_num
def __iter__(self):
counter = 0
while counter < self.max_num:
yield counter
counter += 1
obj = Myrange(3)
for item in obj:
print(item)
总结
可迭代对象 含==iter==方法,且该方法返回一个迭代器 迭代器对象 含==iter==方法和==next==方法,其中 iter 方法返回对象自身(self), next 方法返回迭代的数据,没有数据时需要抛出 StopIteration 异常,以终止迭代 生成器 函数中只要有==yield==,那么返回就是一个生成器(==generator==)对象,生成器类的内部声明了:ietr,next方法。生成器实际是一种特殊的迭代器
#迭代器
from collections.abc import Iterator
#可迭代对象
from collections.abc import Iterable
a = [1,2,3] # a是可迭代对象:只有__iter__,没有__next__
print('a是迭代器吗',isinstance(a,Iterator))
print('a是可迭代对象吗',isinstance(a,Iterable))
b = a.__iter__() #通过调用一个可迭代对象的__iter__方法,得到的是一个迭代器b:有__iter__,也有__next__
print('b是迭代器吗',isinstance(b,Iterator))
print('b是可迭代对象吗',isinstance(b,Iterable))
#执行结果:
'''
a是迭代器吗 False
a是可迭代对象吗 True
b是迭代器吗 True
b是可迭代对象吗 True
'''
#所以,判断一个对象是否是 可迭代对象,使用 isinstance(obj,Iterator) == False 和 isinstance(obj,Iterable) == True
#判断一个对象是否是 迭代器 使用 isinstance(obj,Iterator) == True