【python】中的可迭代对象、迭代器、生成器

结论

  • 凡是实现了__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                                          # 是迭代器, 生成器是一个特殊的迭代器
"""

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值