结论
- 凡是实现了__iter__() 方法的类都称之为可迭代对象,但 __iter__() 方法的返回值只能是迭代器和生成器
- for 循环的本质是先调用 __iter__() 方法,然后不断调用返回值的 __next__() 方法,直至报出异常 StopIteration,可迭代对象的返回值一定是迭代器或生成器,而迭代器和生成器内部都具有 __next__() 方法,所以可迭代对象一定可以用于 for 循环
- 凡是实现了 __iter__() 方法和 __next__() 方法的类都称之为迭代器
- 凡是包含 yield 的函数都会自动生成一个同名的包含 __iter__() 方法和 __next__() 方法的类,这个类称之为生成器,所以生成器是一个特殊的迭代器
- 在类中只要实现了 __getitem__(),则会自动生成 __iter__() 方法,所以凡是实现了__getitem__()方法的类也都称之为可迭代对象
- 可迭代对象不一定是迭代器,但迭代器一定是可迭代对象
案例 1
凡是实现了__iter__() 方法的类都称之为可迭代对象,凡是实现了 __iter__() 方法和 __next__() 方法的类都称之为迭代器
from collections.abc import Iterator
# 定义一个可迭代对象,同时也是迭代器
class MyClass1():
def __init__(self, max_num):
self.current = 0
self.max_num = max_num
def __iter__(self): # 实现了__iter__()方法并不报错的类就是可迭代对象,对返回值类型有要求,否则报错
return self # 并不要求必须返回self,只要是迭代器、生成器就可以,self本身是迭代器
def __next__(self): # 同时实现了__iter__()和__next__()的类就是迭代器
if self.current < self.max_num:
val = self.current
self.current += 1
return val
else:
raise StopIteration # __next__()方法中要求有StopIteration, 否则无法终止,但不是必须
for value in MyClass1(3): # for循环的本质是先调用__iter__(),然后不断调用返回值的__next__(),直至报出异常StopIteration
print(value)
print(iter(MyClass1(3))) # iter(Myclass1(3))等效于Myclass1(3).__iter__()
print(isinstance(MyClass1(3), Iterator))
"""
0 1 2 # 可用for循环, 只要是可迭代对象都可以用for循环
<__main__.Myclass1 object at 0x79a05a1c7fd0> # 说明是可迭代对象, 如果不是可迭代对象会报错
True # 说明是迭代器
"""
# 定义一个可迭代对象,同时也是迭代器
class MyClass2():
def __init__(self, max_num):
self.current = 0
self.max_num = max_num
def __iter__(self): # 实现了__iter__()方法并不报错的类就是可迭代对象,对返回值类型有要求,否则报错
return iter([3, 4, 5]) # 并不要求必须返回self,只要是迭代器、生成器就可以,iter(List)中包含__next__()方法
def __next__(self): # 同时实现了__iter__()和__next__()的类就是迭代器
if self.current < self.max_num:
val = self.current
self.current += 1
return val
else:
raise StopIteration # __next__()方法中要求有StopIteration, 否则无法终止,但不是必须
for value in MyClass2(3): # for循环的本质是先调用__iter__(),然后不断调用返回值的__next__(),直至报出异常StopIteration
print(value)
object2 = MyClass2(3)
for _ in range(3):
print(next(object2)) # next(object2)等效于object2.__next__()
print(iter(MyClass2(3))) # iter(Myclass2(3))等效于Myclass2(3).__iter()__
print(isinstance(MyClass2(3), Iterator))
"""
3 4 5 # 可用for循环, 但for循环与自身的__next__()无关, 调用的是返回值的__next__()
0 1 2 # 自身的__next__()方法可以直接被调用, 超出取值范围会报出异常StopIteration
<list_iterator object at 0x7a2e7013bd90> # 说明是可迭代对象, 如果不是可迭代对象会报错
True # 说明是迭代器
"""
案例 2
凡是实现了__iter__() 方法的类都称之为可迭代对象
from collections.abc import Iterator
# 定义一个可迭代对象,但不是迭代器
class MyClass3():
def __iter__(self): # 实现了__iter__()方法并不报错的类就是可迭代对象,对返回值类型有要求,否则报错
return iter([0, 1, 2]) # 并不要求必须返回self,只要是迭代器、生成器就可以,iter(List)中包含__next__()方法
for value in MyClass3(): # for循环的本质是先调用__iter__(),然后不断调用返回值的__next__(),直至报出异常StopIteration
print(value)
print(iter(MyClass3())) # iter(Myclass3())等效于Myclass3().__iter()__
print(isinstance(MyClass3(), Iterator)) # 类中没有实现自己的__next__(),所以不是迭代器,但能用在for循环的原因是调用了List的__next__()
"""
0 1 2 # 可用for循环, 只要是可迭代对象都可以用for循环
<list_iterator object at 0x7a2e7013bd90> # 说明是可迭代对象, 如果不是可迭代对象会报错
False # 说明不是迭代器, 没有实现自己的__next__()方法
"""
案例 3
在类中只要实现了 __getitem__(),则会自动生成 __iter__() 方法,所以凡是实现了__getitem__()方法的类也都称之为可迭代对象
from collections.abc import Iterator
# 定义一个可迭代对象,但不是迭代器
class MyClass4():
def __init__(self):
self.data = [0, 1, 2]
def __getitem__(self, index): # __getitem__()方法会自动实现__iter__()方法,但不会自动实现__next__()方法
return self.data[index]
for value in MyClass4(): # for循环的本质是先调用__iter__(),然后不断调用返回值的__next__(),直至报出异常StopIteration
print(value)
print(iter(MyClass4())) # iter(Myclass4())等效于Myclass4().__iter()__
print(isinstance(MyClass4(), Iterator)) # 类中没有实现自己的__next__(),所以不是迭代器,但能用在for循环的原因是调用了List的__next__()
"""
0 1 2 # 可用for循环, 调用的是返回值的__next__(), 返回值是iter(self.data)
<iterator object at 0x7172911bbd30> # 说明是可迭代对象, 如果不是可迭代对象会报错
False # 说明不是迭代器, 没有实现自己的__next__()方法
"""
案例 4
凡是包含 yield 的函数都会自动生成一个同名的包含 __iter__() 方法和 __next__() 方法的类,这个类称之为生成器,所以生成器是一个特殊的迭代器
from collections.abc import Iterator
# 定义一个可迭代对象,但不是迭代器
class MyClass5():
def __init__(self):
self.data = [0, 1, 2]
def __iter__(self): # 实现了__iter__()方法并不报错的类就是可迭代对象,对返回值类型有要求,否则报错
for i in range(len(self.data)): # 并不要求必须返回self,只要是迭代器、生成器就可以,包含yield返回生成器
yield self.data[i] # 不需要加异常StopIteration
for value in MyClass5(): # for循环的本质是先调用__iter__(),然后不断调用返回值的__next__(),直至报出异常StopIteration
print(value)
print(iter(MyClass5())) # iter(Myclass5())等效于Myclass5().__iter()__
print(isinstance(MyClass5(), Iterator)) # 没有自己的__next__()所以不是迭代器
print(isinstance(iter(MyClass5()), Iterator)) # __iter__()返回值是一个生成器,生成器内部会自动实现自己的__iter__()方法和__next__()方法,详见下面fib()
"""
0 1 2 # 可用for循环, 只要是可迭代对象都可以用for循环
<generator object MyClass5.__iter__ at 0x7a2e701e2350> # __iter__()方法返回的是生成器, 说明是可迭代对象, 如果不是可迭代对象会报错
False # 说明不是迭代器, 但可以用for循环的原因是, 返回的生成器内部自动实现自己的__iter__()方法和__next__()方法
True # 包含yield语句的__iter__(self)自动生成一个生成器, 生成器也是一个类, 注意这个类是MyClass5内部的一个类
"""
# 定义一个可迭代对象,同时也是迭代器
def fib(end=1000): # 自动构建一个名为fid的类,并自动构建__iter__()方法和__next__()方法,使之成为可迭代对象和迭代器
prev, curr = 0, 1
while curr < end:
yield curr # 不需要加异常StopIteration
prev, curr=curr, curr+prev
for value in fib(): # for循环的本质是先调用__iter__(),然后不断调用返回值的__next__(),直至报出异常StopIteration
print(value)
object_fib = fib()
for _ in range(3): # 能用for循环,因为生成器自动构建__iter__()方法和__next__()
print(next(object_fib)) # next(object_fib)等效于object_fib.__next__()
print(iter(fib())) # iter(fib())等效于fib().__iter()__
print(isinstance(fib(), Iterator)) # 是迭代器,原因是生成器自动构建__iter__()方法和__next__()
"""
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 # 说明生成器会自动构建__iter__()方法和__next__()方法
1 1 2 # 说明生成器会自动构建__next__()方法
<generator object fib at 0x7a2e701e2350> # __iter__()方法返回的是生成器, 说明是可迭代对象, 如果不是可迭代对象会报错
True # 是迭代器, 生成器是一个特殊的迭代器
"""