解惑python3 可迭代对象(iterable)、迭代器(iteration)、生成器(generator)

 注意:

1.构建可迭代对象和迭代器时经常会出现错误,原因是混淆了二者。

(1)可迭代对象有个__iter__( ) 方法,调用该方法每次都实例化一个新的迭代器。

(2)迭代器要实现__next__( )方法返回单个元素,还要实现__iter__( )方法返回本身(self)

因此,迭代器可以迭代,但是可迭代对象不是迭代器!!!

导入模块:from collections.abc import Iterable,Iterator

可以用 isinstance( x , Iterable ) 判断x是否为可迭代对象;

可以用 isinstance( x , Iterator ) 判断x是否为迭代器;

2.生成器是特殊的迭代器

一、可迭代对象 iterable

一句话:“实现了__iter__方法的对象就叫做可迭代对象”

简单点来说能用for循环进行迭代的对象就是可迭代对象。比如:字符串、列表、元组、集合...

注意:

1.调用可迭代对象的__iter__() 方法返回一个可迭代对象(iterable)

2.不断调用迭代器的__next__() 方法返回元素

3.直到迭代完成后,处理StopIteration异常

>>> a = [1,2,3]
>>> b = a.__iter__()
>>> print(b)
<list_iterator object at 0x000001E9C5781860>
>>> b.__next__()
1
>>> b.__next__()
2
>>> b.__next__()
3
>>> b.__next__()
Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    b.__next__()
StopIteration

 二、迭代器 iterator

什么叫迭代器?它就是一个带状态的对象,他能在你调用 next() 方法的时候返回容器中的下一个值。

任何实现了__iter____next__()方法的对象都是迭代器。

标准的迭代器接口有两个方法:

(1)__next__( ) :返回下一个可用的元素,如果没有元素,抛出StopIteration异常。

(2)__iter__( ) :返回self,以便在应该使用可迭代对象的地方使用迭代器,比如for循环中。

迭代器就像一个懒加载的工厂,等到有人需要的时候才给它生成值返回,没调用的时候就处于休眠状态等待下一次调用。直到无元素可调用,返回StopIteration异常。

例子如下实现斐波那契数列:

>>> class Fib():
	def __init__(self,max):
		self.n = 0
		self.prev = 0
		self.curr = 1
		self.max = max
	def __iter__(self):
		return self
	def __next__(self):
		if self.n<self.max:
			value = self.curr
			self.curr += self.prev
			self.prev = value
			self.n += 1
			return value
		else:
			raise StopIteration

		
>>> f = Fib(5)
>>> next(f)
1
>>> f.__next__()
1
>>> next(f)
2
>>> next(f)
3
>>> next(f)
5
>>> next(f)
Traceback (most recent call last):
  File "<pyshell#32>", line 1, in <module>
    next(f)
  File "<pyshell#25>", line 17, in __next__
    raise StopIteration
StopIteration

三、生成器 generator

注意:生成器是特殊的迭代器(反之不成立),不需要写__iter__( )、__next__( ),只需要一个yield关键字。

在Python中,这种一边循环一边计算的机制,称为生成器:generator

使用next()函数和send()函数恢复生成器

(1)next()函数:next的作用是唤醒并继续执行

(2)send()函数:send的作用是唤醒并继续执行,发送一个信息到生成器内部

生成器类似于返回值为数组的一个函数,这个函数可以接受参数,可以被调用,但是,不同于一般的函数会一次性返回包括了所有数值的数组,生成器一次只能产生一个值,这样消耗的内存数量将大大减小,而且允许调用函数可以很快的处理前几个返回值,因此生成器看起来像是一个函数,但是表现得却像是迭代器.

python提供了两种基本的方式:

(1)生成器函数:用def 定义的利用关键字yield一次性返回一个结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行。如下:

# 例子1:斐波那契数列

def Fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1
    return '啊哈没有数据了喔'


f = Fib(10)
# 使用一个循环捕获最后return 返回的值,保存在异常StopIteration的value中
while 1:
    try:
        x = next(f)
        print('f:', x)
    except StopIteration as e:
        print('生成器最后返回的值:', e.value)
        break


# 例子2:

def foo():
    print("first")
    count=yield
    print(count)
    yield

f = foo()   
f.send(None)
f.send(2)

"""
例子2解释:
f = foo() 返回一个生成器
f.send(None) 进行函数执行代码,遇到count = yield,冻结并跳出函数体
f.send(2) 再次进入函数体,接着冻结的代码继续执行,把2传给变量count,
          打印count,遇到yield冻结并跳出函数
"""

(2)生成器表达式:生成器表达式是列表推导式的生成器版本,看起来像列表推导式,但是它返回的是一个生成器对象而不是列表对象。

from collections.abc import Iterable,Iterator
a = (x for x in range(10))
print(isinstance(a,Iterable))  # True
print(isinstance(a,Iterator))  # True

发布了41 篇原创文章 · 获赞 29 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_43930694/article/details/104605441