【Python】生成器与迭代器
迭代器(iterator)
判断是否是迭代器和可迭代对象
from collections import Iterator #迭代器
from collections import Iterable #可迭代对象
print(isinstance(s,Iterator)) #判断是不是迭代器
print(isinstance(s,Iterable)) #判断是不是可迭代对象
明确以下三个概念:
**可迭代对象(Iterable)
迭代器(Iterator)
迭代(Iteration)**
(一)可迭代对象(Iterable)
(1) python内置的几种数据结构:字符串(str),列表(list),元组(tuple),字典(dict),集合(set)都是可迭代对象.
(2) Python中任意的对象,只要它定义了可以返回一个迭代器的__iter__方法,或者定义了可以支持下标索引的__getitem__方法,那么它就是一个可迭代对象。简单说,可迭代对象就是能提供迭代器的任意对象。
from collections import Iterable
class MyIter:
def __init__(self):
pass
def __iter__(self):
yield 1 # __iter__()需要返回一个迭代器
a = MyIter() # 对象a就是一个可迭代的对象
print(isinstance(a,Iterable)) #判断是不是可迭代对象
# True
(二) 迭代器(Iterator)
在python3中同时实现在__iter__()和__next__()两个魔法函数的对象,就是迭代器。其中__iter__()方法需要返回一个迭代器, 而__next__()方法返回下一个返回值或者StopIteration。
from collections import Iterator #迭代器
class MyIter:
def __init__(self):
self.cnt = 0
def __iter__(self):
return self
def __next__(self): # 因为实现在__next__,所以自身就是一个迭代器,这里就可以返回自己
return 1
s = MyIter()
print(isinstance(s,Iterator)) #判断是不是迭代器
# True
迭代器可以通过next()方法不断重复获取下一个值,直到所有元素全部输出完之后,返回StopIteration才停止。
# 迭代器可以通过next()方法不断重复获取下一个值,直到所有元素全部输出完之后,返回StopIteration才停止。
def fun_print():
for i in range(2):
yield i+2
a = fun_print()
print(next(a))
print(next(a))
print(next(a))
结果为:
2
3
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-27-76648422ccff> in <module>
9 print(next(a))
10 print(next(a))
---> 11 print(next(a))
StopIteration:
可迭代的对象不能使用next():
list1 = [1,2,5,3,5,6,44,8,5]
next(list1)
# TypeError: 'list' object is not an iterator
注: 对可迭代的对象,使用iter()方法,也会返回一个迭代器,如:
# 对可迭代的对象,使用iter()方法,也会返回一个迭代器,如:
a = iter([1, 2, 3, 4])
print(a)
# <list_iterator object at 0x000002B6BF679550>
(三) 迭代(Iteration)
用简单的话讲,它就是从某个地方(比如一个列表)取出一个元素的过程。当我们使用一个循环来遍历某个东西时,这个过程本身就叫迭代。
生成器(generator)
创建生成器的两种方法:生成器包括生成器表达式(类似于推导式)和生成器函数。
(一)生成器表达式
把一个列表生成式的[]中括号改为()小括号
# 创建生成器: 类似列表推导式
a = [i+1 for i in range(3)] # 列表生成式
print(a)
b = (i+1 for i in range(3)) # 生成器
print(b)
print(next(b)) # 使用next()函数获取下一个元素
print(next(b))
print(next(b))
结果为:
[1, 2, 3]
<generator object <genexpr> at 0x000002B6C0187900>
1
2
3
(二) 生成器函数
# 生成器函数
def myGen():
x = range(1, 11)
for i in x:
yield i + 2 # 不用return语句, 使用yield 语句
print(myGen())
for x in myGen():
print(x, end=",")
结果为:
<generator object myGen at 0x000002B6C0227660>
3,4,5,6,7,8,9,10,11,12,
生成器可以理解成一种特殊的迭代器。它和迭代器的区别在于,生成器并不是一上来就把所有值装载进内存,因而也不会占用大量的内存,只是在需要使用next()函数获取值的时候,才会取一个值返回,内存开销非常小。而是在运行时生成值。要想拿到每一个元素,就需要循环遍历或者使用。
(1)“for”循环进行循环遍历
b = (i+1 for i in range(3)) # 生成器
for i in range(3):# 一个“for”循环,
print(i)
print(list(b)) # 传递给任意可以进行迭代的函数和结构。
结果为:
0
1
2
[1, 2, 3]
注:在一个操作中(如 for 循环)生成器不能读取迭代过的数据
(2)使用函数获取生成器元素
next() 系统自定义函数
__next__() 生成器自定义函数
def fibon(n):
a = b = 1
for i in range(n):
yield a
a, b = b, a + b
a = fibon(4) # 获取生成器对象
print(next(a)) # 系统函数: next(g)
print(a.__next__()) # 生成器自定义函数
print(a.__next__()) # 生成器自定义函数
'''
1
1
2
'''
生成器的应用实例:
#计算斐波那契数列的生成器:。
# generator version
def fibon(n):
a = b = 1
for i in range(n):
yield a
a, b = b, a + b
for x in fibon(10):
print(x)
'''
1
1
2
3
5
8
13
21
34
55
'''
参考文献:
https://blog.csdn.net/weixin_40107510/article/details/93378198
https://blog.csdn.net/answer3lin/article/details/86493988