python的装饰器、迭代器、yield_Python学习日记(5)简单了解迭代器、生成器、装饰器、上下文管理器...

迭代器

迭代器只不过是一个实现了迭代器协议的容器对象。它基于以下两个方法。

__ next __:返回容器的下一个元素。

__ iter __:返回迭代器本身。

实际上,迭代器表现了程序底层的概念和特性,在程序中,你可以不必使用迭代器,但是理解迭代器,却是对生成器这样一个常用特性理解很有帮助。

学习迭代器,我基本上通过2个例子来理解迭代器的特性。(PS:我发现我之前记得笔记不是很详细,所以这一篇记录详细一些……不然我有时候一些点我自己看的时候都要想一下,吐血,果然没什么灵性……)

好了,上代码:

a = iter([11,22,33])print(next(a))print(next(a))print(next(a))-------------------------

11

22

33[Finishedin 0.2s]

这里,我创建了一个非常简陋的迭代器,使用iter()函数,这个函数在上述的代码中接收了一个列表作为参数,并赋值给a这个变量。

那么此时,a就是一个迭代器了。当然,此时创建的这个a的迭代器非常的简陋,就好比我要造飞机,结果你用纸给我叠了一个。不过飞机的特性还是有的,可以算是飞机了,只不过是纸飞机。

迭代器使用:通过函数next()来使用,next()函数参数接收一个迭代器,并在每一次执行的时候,依次调取迭代器中的值,并返回出来。

简单理解:next()函数呢,就好比游戏登录器,游戏就好比迭代器,没有登录器你玩不了游戏,所以,没next()这玩意你用不了迭代器,想用迭代器,你需要用next()这个方法调,next()这个方法有一个特点,从头开始调,每次调一个。

那么,为什么说我们用iter()创建的迭代器是纸飞机呢?

看代码思考2个问题:

1,每次调用是进行依次调用的,上述代码调用的刚好是个列表,如果,调用列表中最后一个值之后,继续调用,会怎么样呢?

a = iter([11,22,33])print(next(a))print(next(a))print(next(a))print(next(a))-------------------------StopIteration

[Finishedin 0.2s with exit code 1]

可以看到,迭代器中只有3个值,而我调用了4次,所以在第四次调用的时候,返回了一个StopIteration异常。这是好事,异常代表着迭代的完结,我们可以利用异常做点事情。

2,为什么说纸飞机呢,这个迭代器有一个非常不好的点,那就是迭代的次数并非我们想要的,如果我们想迭代100次,总不至于写一个有100个元素的列表吧?当然,你可以说我可以用range()来解决这个问题呀。

a = iter(range(4))print(next(a))print(next(a))print(next(a))print(next(a))-------------------------------01

2

3[Finishedin 0.2s]

可是,实际上,并没有解决触发异常的问题。并且每一次的迭代,都需要next()来手工进行,那么,我们来做一个真正的迭代器。

classCountDown():def __init__(self,step):

self.step=stepdef __next__(self):if self.step <=0:raiseStopIteration

self.step= self.step - 1

returnself.stepdef __iter__(self):returnself

ff= CountDown(5)for i inff:print(i)-------------------------------------

4

3

2

10

[Finishedin 0.2s]

__ next __:返回容器的下一个元素。

__ iter __:返回迭代器本身。

这个类就非常明确了,接收迭代次数,并且每次迭代减1,触发异常停止迭代。实际上,迭代只是一种概念,迭代器则提供了一种专门的方法,并非在python程序中唯一的迭代动作!

生成器

生成器是一种优雅的方法,他可以让编写返回元素序列的函数代码变得简单,高效。

实际上,我们常用的方法:range()

for i in range(10):print(i)

也是生成了一个列表来供我们遍历,在python3中,本质也是生成器。

当然,我们也可以自己写一个列表生成器,不使用range()

defMaker(num):

a=0whileTrue:

b=a

a= a + 1num= num - 1

yieldbif num <=0:breakff= Maker(10)

a= [i for i in Maker(10)]

b= [x for x in range(10)]print(a)print(b)--------------------------------------------[0,1, 2, 3, 4, 5, 6, 7, 8, 9]

[0,1, 2, 3, 4, 5, 6, 7, 8, 9]

[Finishedin 0.2s]

看,我们自己写了一个生成器方法Maker(),这个方法接收一个参数,来表示生成列表数量,与range()函数的方法是一样的。(起码在调用看来是的)

代码中的:yield语句,表示暂停生成器,返回结果。是不是有点像return?可以想一想,是有区别的,一个是暂停,返回后继续执行后面的代码,return返回后就不在执行啦。

实际上,生成器可以执行复杂的生成过程,不过具体还是要看你要实现什么需求。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值