python 迭代器和生成器

python迭代器和生成器

python迭代器

为什么要写这个文档,感觉自己学了这么久python,感觉白学了,一直都用C++的思想去看python代码,基础完全没学好,感觉很混乱。

for(int i=0;i<100;i++)
	cout<<i<<endl;
for i in range(0,100)
	print(i)

在C++,for循环是首先执行i=0,然后在比较i<100循环中的语句i++ 之间重复,直到不满足判断。
而python的for循环,range返回的是一个迭代器。我们可以将循环理解成下列步骤。首先,range生成一个列表,range 通过__iter__函数将这些数据转变为一个迭代器,每次for循环会执行一次__next__函数调用里面的数据,而访问到数组最后没有数据的时候,会弹出一个StopIteration,迭代结束。
再加一点,其实确切的说,不只是range,,而更应该是for in 这中语句就会抽取出对应的迭代器,像下列代码,没有range,也能实现for循环,可能是python的一个语法包容性吧,具体python编译这些代码的底层我还没有学到,可能以后会写一篇文档吧。

# 迭代列表
L = [1,2,3,4,5]
for element in L:
    print(str(element) * 3)
# 迭代字符串
S = 'PYTHON'
for s in S:
	print(s * 3)
# 迭代元组
L = (1,2,3,4,5)
for element in L:
    print(str(element) * 3)
# 迭代集合
G = {'Ruo', 'Data', 'Python'}
for g in G:
    print(g)
# 迭代文件
for line in open('ex.txt'):
    print(line, end='')

这就是python和C++for循环的区别。

生成器

讲完迭代器,引申一个python生成器的概念。

def fib(n):
    a, b = 0, 1
    for _ in range(n):
        a, b = b, a + b
        yield a
        
def main():
	for val in fib(20):
	    print(val)
	    
if __name__ == '__main__':
	main()

这里面的函数返回并不是使用一个return,而是使用一个yield,这两者有什么区别呢,如果我们使用return来完成上述的代码,就应该是这样

def fib(n):
	a, b = 0, 1
	for _ in range(n):
		a, b = b, a + b
	return a
def main():
	for val in range(20):
		print(fib(val))

我猜很多人可能是写这种代码的,但是我们会发现,下面这份代码总共运行a, b = b, a + b 共210次,而上面有yield的代码只执行了20次。
ps: 有人肯定会说,你直接把for循环写在main函数里不就行了,或者是把print写在fib里面。但是本文讨论的是在函数中return和yield的区别,就不要吹毛求疵了。

然后我们来讲讲yield,讲yield就离不开生成器,包含yield的函数本质上不可以把它看成一个函数,它是一个生成器。而生成器是一种特殊的迭代器,这就为什么我一开始需要讲迭代器的原因。
上一小结里的迭代器,每次会按照__next__方法依次生成下一个数据,因此当前状态需要保存,而实现这些操作我们可以用一种更强大的语法来实现,就是生成器

L = [ x*2 for x in range(5)]  # 列表推导式
print(L)    # [0, 2, 4, 6, 8]  
G = ( x*2 for x in range(5))	# 生成器
print(G)  
# <generator object <genexpr> at 0x7f43c0818780>
# 调用生成器  这是python3 和python2的next()不一样
print(G.__next__())  # 输出 0
print(G.__next__())  # 输出 2

当然,我们一般也不会建个生成器去不停__next__() 我们一般就将它用在for循环,或者就是函数迭代上,现在回到那个fibnaci函数里去。
含有yield的函数,即生成器,它本身会包含一个功能,记录当前运行的状态,再次访问生成器时会从原先的状态继续运行,直到生成器停止迭代。在上面代码就是每次for循环暂停一次,下次进入生成器在继续循环,直到循环结束
ps:python3 生成器可以加return,当生成器遇到return时,当前的生成器就被结束了。

def fib(n):
	a, b = 0, 1
	for _ in range(n):
		a, b = b, a + b
		yield a
		return a
def main():
	for val in fib(20):
		print(val)
if __name__ == '__main__':
	main()
# 最终只会输出 1 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值