python基础知识_迭代器和生成器_2

本文介绍了Python中的迭代器和生成器。迭代器通过实现`__iter__`和`__next__`方法来定义,当没有数据时抛出`StopIteration`异常。通过`next()`函数或`for`循环可以获取迭代器的值。生成器是一种特殊的迭代器,由包含`yield`的函数定义。可迭代对象是指类中有`__iter__`方法并返回一个迭代器的对象。
迭代器的定义:
  1. 当类中定义了__iter__和__next__两个方法;
  2. __iter__方法需要返回对象本身,即:self;
  3. __next__方法,返回下一个数据,如果没有数据了,则需要抛出一个StopIteration的异常。
# 创建迭代器类
class IT(object):
    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
    
# 根据类实例化创建一个迭代器对象:
obj1 = IT()

v1 = obj1.__next__()
print(v1)

v2 = next(obj1)   # 等价于 v2 = obj1.__next__();next()是python的内置函数,可帮我们自动去执行.__next__()函数python
print(v2)

v3 = next(obj1)
print(v3)
1
2



---------------------------------------------------------------------------

StopIteration                             Traceback (most recent call last)

~\AppData\Local\Temp\ipykernel_12184\3855014687.py in <module>
     22 print(v2)
     23 
---> 24 v3 = next(obj1)
     25 print(v3)
     26 


~\AppData\Local\Temp\ipykernel_12184\3855014687.py in __next__(self)
     10         self.counter += 1
     11         if self.counter == 3:
---> 12             raise StopIteration()
     13         return self.counter
     14 


StopIteration: 
obj2 = IT()
for item in obj2:
    print(item)
1
2

解析:

  1. IT 类有__iter__和__next__函数,且__iter__返回self, __next__规定了没有数据,就抛出StopInteration异常,所以IT类是一个迭代器类;
  2. obj1是迭代器类实例化的对象,所以obj1是迭代器对象;
  3. 迭代器对象可通过next函数取值,如果取值结束则自动抛出StopInteration。
  4. 迭代器对象可通过for进行循环;for循环的内部机制是:先执行迭代器对象的__iter__方法,然后将返回值(也就是迭代器对象本身obj2)获取到,然后不断执行next,将返回的结果赋值给item,(有异常StopInteration 则终止循环)
  5. 迭代:一步一步向前进,就比如开发一个软件的迭代周期一样。
生成器

定义:有yied的函数就叫生成器

## 创建生成器函数
def fun():
    yield 1
    yield 2
    
# 创建生成器对象(内部是根据生成器类generator创建的对象),生成器类的内部也声明了:__iter__、__next__方法
obj3 = fun()

v1 = next(obj3)
print(v1)

v2 = next(obj3)
print(v2)

v3 = next(obj3)
print(v3)

1
2



---------------------------------------------------------------------------

StopIteration                             Traceback (most recent call last)

~\AppData\Local\Temp\ipykernel_12184\1829462556.py in <module>
     12 print(v2)
     13 
---> 14 v3 = next(obj3)
     15 print(v3)


StopIteration: 
obj4 = fun()
for item in obj4:
    print(item)
1
2

解析:
如果按照迭代器的规定来看,其实生成器也是一种特殊的迭代器(生成器也是一种特殊的迭代器)

可迭代对象

如果一个类中有__iter__方法且返回一个迭代器对象:则我们称这个类创建的对象为可迭代对象

class Foo():
    def __iter__(self):
        return 迭代器对象(生成器对象)
    
obj = Foo()  # 可迭代对象

# 可迭代对象是可以使用for进行循环,在循环内部:先执行__iter__方法,获取其迭代器对象,然后再在内部执行这个迭代器对象的next功能,逐步取值。
## 迭代器类
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()
    
obj = Foo()  # 可迭代对象

for item in obj:   # 循环可迭代对象时,内部先执行obj.__iter__并获取迭代器对象;然后不断的执行迭代器对象的next方法
    print(item)
1
2
## range 示例
v1 = range(10)
dir(v1)   # 有__iter__方法,所以是一个可迭代对象
['__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']
v2 = v1.__iter__()
dir(v2)  # v2 有__iter__和__next__方法,所以是迭代器对象
['__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__']
print(next(v2))
0
print(next(v2))
1
print(next(v2))
2
## 生成自定义的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 Xrange:
    def __init__(self,num):
        self.max_num = num
        
    def __iter__(self):
        return IterRange(self.max_num)
    
obj = Xrange(5)

for item in obj:  ## 执行for循环时:先执行__iter__方法,返回一个IterRange对象,同时还进行参数传递,然后不断执行__next__方法取值
    print(item)
0
1
2
3
4
## 基于生成器实现range功能
class Xrange:
    def __init__(self, num):
        self.max_num = num
        
    def __iter__(self):
        counter = 0
        while counter < self.max_num:
            yield counter
            counter += 1
            

obj = Xrange(6)
for item in obj:
    print(item)
0
1
2
3
4
5
# 常见的数据类型:列表、元组、字典
v11 = list([11,22,33,44])  
dir(v11) # 包含__iter__方法,所以是可迭代对象
['__add__',
 '__class__',
 '__contains__',
 '__delattr__',
 '__delitem__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__getitem__',
 '__gt__',
 '__hash__',
 '__iadd__',
 '__imul__',
 '__init__',
 '__init_subclass__',
 '__iter__',
 '__le__',
 '__len__',
 '__lt__',
 '__mul__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__reversed__',
 '__rmul__',
 '__setattr__',
 '__setitem__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 'append',
 'clear',
 'copy',
 'count',
 'extend',
 'index',
 'insert',
 'pop',
 'remove',
 'reverse',
 'sort']
# v12 = v11.__iter__()
v12 = iter(v12)
dir(v12)   # 包含__iter__和__next__方法,所以是迭代器对象,可通过next取值
['__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__']
# 迭代器对象和可迭代对象的判断
from collections.abc import Iterator, Iterable

v1= [44,55,66]
print(isinstance(v1, Iterator))
print(isinstance(v1, Iterable))
False
True
from collections.abc import Iterator, Iterable
va= [44,55,66]
vb = iter(va)
print(isinstance(vb,Iterator))
print(isinstance(vb,Iterable))
True
True
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值