Python:迭代器、生成器、可迭代对象

1. 迭代器
"""迭代器类型定义:
	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__()  # 1
# v2 = obj1.__next__()  # 2
# v3 = obj1.__next__()  # 抛出异常

print(next(obj1))  # 1  用内置函数next(),自动调用对象的__next__方法
print(next(obj1))  # 2
# print(next(obj1))  # 抛出异常
		
obj2 = IT()
for item in obj2:  # 首先执行对象的__iter__方法并获取返回值(迭代器对象),然后反复执行next(对象)
    print(item)

迭代器对象支持通过next取值,如果取值结束则自动抛出StopIteration
for循环内部在循环时,先执行__iter__方法,获取一个迭代器对象,然后不断执行next取值(有异常StopIteration则中止循环)

2. 生成器
  • 生成器函数:是由函数+yield关键字创造出来的写法,在特定情况下,可节省内存
  • 生成器函数判断标准:函数中是否存在yield关键字
  • 生成器对象:执行生成器函数时,返回一个生成器对象
  • 注:执行生成器函数时,函数内部代码不会执行,而是返回一个生成器对象
  • next方法中放生成器对象,进入生成器函数并执行其中的代码(从上次yield返回位置继续向下执行),代码示例:
    def func():
    	"""生成器函数"""
    	for i in range(10):
    		yield i
    
    """创建生成器对象(内部是根据生成器类generator创建的对象),生成器类的内部也声明了:__iter__、__next__方法"""
    data = func()  
    n1 = next(data)  # 0
    n2 = next(data)  # 1
    
    按照迭代器的定义来看,生成器也是一种特殊的迭代器类
  • 生成器补充:
    • 生成器对象的send方法可往生成器对象中传参,示例:
      def func():
      	for i in range(10):
      		v = yield i
      		print(v)
      	
      data = func()  # 创建生成器对象
      n1 = data.send(None)   # 首次必须send(None)
      # n1 = 0,此时生成器对象内执行停留在yield 0,v尚未被赋值
      
      n2 = data.send(333)  
      # 生成器内首先执行v赋值为333,然后执行print、进入下次循环、yield 1;此时n2 = 1
      
      注:生成器对象的send方法首次传参必须:生成器对象.send(None)
    • yield from
      Python3.3之后引入yield from,可在生成器中yield from另一个生成器对象
  • 生成器特点总结:记录在函数中的执行位置,下次执行next时,从上一次的位置基础上继续向下执行
  • 应用场景:需要在内存中创建很多数据时,可以基于生成器来实现一点一点生成(即用即生产),以节省内存开销
3. 可迭代对象
  • 如果一个类中有__iter__方法且返回一个迭代器对象,则称这个类创建的对象为可迭代对象
    class Foo(object):
    	def __iter__(self):
    		return 迭代器对象(生成器对象)
    
    obj = Foo()  # obj是可迭代对象
    
    # 可迭代对象是可以使用for来进行循环,在循环内部其实是先执行__iter__方法,获取其迭代器对象,然后再在内部执行这个迭代器对象的next功能,逐步取值
    for item in obj:
    	pass
    
  • 迭代器实现可迭代对象:
    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
    
    class Foo(object):
    	"""可迭代对象类"""
    	def __iter__(self):
    		return IT()
    
    obj = Foo()  # 可迭代对象
    for item in obj:  # 循环可迭代对象时,内部先执行obj.__iter__并获取迭代器对象;不断地执行迭代器对象的next方法
    	print(item)
    
  • 生成器实现可迭代对象
    def func():
        for i in range(10):
            yield i
            
    class Foo(object):
    	def __iter__(self):  # 与返回生成器对象return func()效果相同
    		for i in range(10):  
    			yield i
    	"""
    	1. 可以在__iter__方法内写入生成器函数内部的代码,不用返回任何内容,如上;
    	2. 也可以返回生成器对象,例如:
    	def __iter__(self):
            return func()
    	3. 但不能直接执行生成器函数却不返回任何内容,会报错;
    	例如:
    	def __iter__(self):
    		func()  # 执行生成器函数,报错
    	或:
    	def __iter__(self):
    		func  # 也会报错
    	"""
    	
    obj = Foo()
    for item in obj:
    	print(item)
    
4. python中也有特定方法可检查迭代器对象和可迭代对象
from collections.abc import Iterator, Iterable

v1 = [11, 22, 33]
print(isinstance(v1, Iterator))  # False
print(isinstance(v1, Iterable))  # True
v2 = v1.__iter__()
print(isinstance(v2, Iterator))  # True
print(isinstance(v2, Iterable))  # True
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值