如何理解Python迭代器,并实现一个迭代器
Admin 2022-08-15 群英技术资讯 271 次浏览
最近在看Python基础教程(第三版),是之前python课的课本,但是之前没读过,虽然python一直用得挺多,但重新读读收获还挺大。这里做个笔记。
先是迭代器是什么并简单实现一个迭代器,然后是实现了一些range()。
迭代器是像循环一样重复很多次,但不会像列表那样一次性全部生成,而是需要用的时候再生成,就节省了内存资源。有时可能只想一个个地获取值,而不是用列表一次性获取,列表可能占用太多内存,并且有时没办法使用列表,列表的长度会到无穷大。
简单的说,迭代器类中:
根据上面描述可以简单写一个迭代器出来
class TestIterator:
value = 0
def __next__(self):
self.value += 1
if self.value > 10: # 到这个条件了没有可返回的了就抛出一个StopIteration异常
raise StopIteration
return self.value # 每次返回下一个
def __iter__(self): # 这里返回它自己
return self
if __name__ == '__main__':
ti = TestIterator()
print(list(ti))
运行的结果是:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
嗯于是就能知道了,关于__iter__和__next__:
实现了方法__iter__的对象是可迭代的,而实现了方法__next__的对象是迭代器。
方法__iter__返回一个迭代器,它是包含方法__next__的对象。
文档中也写得很清楚了,调用__next__时,迭代器应返回其下一个值。如果迭代器没有可供返回的值,则引发StopIteration异常。
iter返回一个迭代器对象,即object.__iter__()。如果指定了sentinel(哨兵),这个迭代器将不断调用直到返回的是sentinel。
然后再来一个斐波那契数列的例子,迭代器对象可以被放进for循环。
class Fibs:
def __init__(self) -> None:
self.a = 0
self.b = 1
def __next__(self):
self.a, self.b = self.b, self.a + self.b
return self.a
def __iter__(self):
return self
if __name__ == '__main__':
fibs = Fibs()
for f in fibs: # 首先会执行__iter__方法获取返回值,就它自己,然后执行一次它的__next__方法,不断循环。
if f > 1000:
print(f)
break
返回这个数列中第一个大于1000的数,是1597。
(base) eisen@pop-os:~$ python3.8
Python 3.8.10 (default, Mar 15 2022, 12:22:08)
[GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> v1 = range(20)
>>> dir(v1)
['__bool__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index', 'start', 'step', 'stop']
这里先看到v1里面只有__iter__,v1为可迭代对象Iterable,让v2 = v1.__iter__()
>>> v2 = v1.__iter__()
>>> dir(v2)
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__length_hint__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__']
可以看到v2既有__iter__又有__next__为迭代器对象。range就是执行v1的__iter__获取到里面的迭代器对象v2,再执行v2的__next__方法...
>>> v2.__next__()
0
>>> v2.__next__()
1
>>> v2.__next__()
2
>>> v2.__next__()
3
>>> v2.__next__()
4
>>> v2.__next__()
5
于是实现一下range就很简单了,在实现的MyRange里面,__iter__方法就生成一个IterRange类的迭代器对象。
class IterRange():
def __init__(self, num):
self.num = num
self.counter = -1
def __iter__(self):
return self
def __next__(self):
self.counter += 1
if self.counter == self.num:
raise StopIteration()
return self.counter
class MyRange():
def __init__(self, num):
self.num = num
def __iter__(self):
return IterRange(self.num)
v1 = MyRange(20)
for i in v1:
print(i)
输出就是把0到19打印出来。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
这篇文章主要介绍python类的继承链,对新手理解类的继承链有一定的帮助,有这方面学习需求的朋友可以参考下,希望大家阅读完这篇文章能有所收获,接下来小编带着大家一起了解看看。
如果一个函数,可以自己调用自己,那么这个函数就是一个递归函数。本文将详细讲解Python中递归函数的使用与原理,感兴趣的可以了解一下
类(class)是python中很重要的一个概念,也是我们面象对象编程中最重要的概念主之一,这篇文章主要给大家介绍了关于python中class类与方法用法的相关资料,需要的朋友可以参考下
这篇文章主要介绍了Python3 中return和yield的区别,return和yield都用来返回值;在一次性地返回所有值场景中return和yield的作用是一样的,但是具体有什么区别呢,带着疑问一起进入下面文章学习详细内容吧
今天就带大家详细总结一下Python闭包和装饰器的相关知识,需要的朋友可以参考下
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008