python中的迭代器对象,python生成器和迭代器理解
本文为您带来了一些关于python的知识,包括关于容器、迭代对象、迭代器和生成器的相关问题。来看看吧,希望对你有帮助。
推荐:python视频教程
刚开始学Python的时候,是不是经常听到大佬们讲容器、迭代器、生成器、列表/集合/字典派生等很多概念。其实并不是老板们没事就抛开专业术语去装B,而是他们得懂这些东西。仅仅知道字符串、列表等基础知识是不够的。尤其是在Python的数据结构方面。
今天我们来谈谈Python中一些比较难的概念,比如容器、迭代器、生成器。让您的Python基础上一层楼!
在Python中,容器是把多种元素组织在一起的数据结构,容器中的元素就可以逐个迭代获取.说白了,它的功能就像它的名字一样:存储东西(数据)。
其实容器是不存在的。它不是一个数据类型,而是一个人造的概念。只是为了方便学习而创造的一个概念词。它可以使用成员资格运算符(in或not in)来确定对象是否在容器内。
当然不是我创造的。我没那么大本事。这是官方创造的。好吧,你不用担心我在教你一些奇怪的名词,别人听不懂……python就是这么叫的。常见的容器类型有列表(list)、元组(tuple)、字符串(str)、字典(dict)以及集合(set ).
由于容器中的数据可以迭代获得,我们必须学习一个新概念:可迭代对象。
在python中,可迭代对象并不是指某种具体的数据类型,它是指存储了元素的一个容器对象.
也就是说,如果容器中没有存储数据,那么它就不是可迭代对象。并非所有容器都是可迭代对象,容器包含但不限于可迭代对象。
注意两个点:
1.许多容器是可迭代对象(容器包含可迭代对象)。
2.可迭代对象不能独立迭代。迭代是通过for完成的,所有可迭代对象都可以通过使用for循环直接访问。for循环应该大家都很熟悉吧?想知道for循环是如何在内部实现的吗?例如,在这个For循环的例子中,为什么我们可以输出列表中的每个元素?它的内部是如何实现的?
其实for循环做了两件事情:
1.使用__iter__()返回1个迭代器,下面会讨论。在这里,我首先知道有这样的事情。
2.使用__next__()获取迭代器中的每个元素。然后我们不使用for循环来输出列表中的每个元素,
L=[1,2,3,4]# for I in l : # print(I)ite=l . _ _ ITER _ _()# Receive ietr()打印的内容(ite)
#打印打印(ite。__下一个_ _())
#第一步打印(ite。__next__())在循环中做第二件事时完成
#第二步打印(ite。__next__())在循环中做第二件事时完成
#第三步打印(ite。__next__())在循环中做第二件事时完成
#对于在循环中执行第二件事时完成的步骤4的输出结果:
可以看到,如果我们去掉打印ite的那行代码,执行效果将和for循环的输出列表中的每一个元素是一样的。for循环的范围限定为4次,实际上是执行一次__iter__()和四次__next__()。也就是说,for循环访问被迭代对象的本质就是这样实现的。
而且for循环本质上做的两件事是缺一不可的,也就是说如果__iter__()先返回迭代器,__next()__就无法获取元素,这正好说明了上面提到的两点中的第二点:一个iterable对象无法独立迭代。
有两个内置函数,原理和本质和他们一样。一般来说,使用内置函数更方便,至少不用写那么多下划线:
内置函数iter()的本质是__inter__(),它也返回一个迭代器。
内置函数next()的本质是__next__(),也是在拥有迭代器后获取元素。
可以看出结果是一模一样的。既然讨论了迭代器,那我们就来看看迭代器是什么。
00-1010正如我们从上面的循环示例中可能看到的,
hp;toolbar:false">只要是实现了__iter__()和__next__()的对象,就是迭代器,迭代器是一个可迭代对象。
总之,迭代器是有__iter__()生成,可以通过__next__()进行调用。既然如此,我们在学Python基础的时候讲过range()是一个可迭代对象,那么它也是可以通过__iter__()生成一个迭代器的。
四、序列
序列在【赋值语句】那个专题文章中我有提过,这里再讲一下,序列也是一个抽象的概念,它包含了列表、元组和字符串,它本身是不存在的,也是便于学习所创造的一个概念词。可迭代对象包含序列,既然序列包含了列表、元组和字符串,前面我们的例子中也涉及到 了,所以说序列可以被iter()和next()使用。
序列可以分为有限序列和无限序列。有限序列就是有范围的,比如说range(10)就已经限定了范围,相反的,无限序列也就是没有限定范围的序列。
我们来生成一个无限序列,这里需要用到1个新模块itertools,itertools用于高效循环的迭代函数集合,它下面有一个方法count(),可生成迭代器且无范围,可以理解为无限迭代器。
通过这个例子我们可以看出来,只要执行一次,next()就会获取一次迭代器里面的内容并逐次获取,我这里只写了4个next(),你多写几次就会多输出几次。
像next()这种什么时候需要就什么时候调用的机制叫做懒加载机制,也叫懒汉式加载;
相反地就有饿汉式加载。比如for循环这种的,只要一执行就会把可迭代器里面的所有对象都获取。
五、列表推导式
列表推导式跟生成器有关,在讲生成器之前,需要先知道什么是列表推导式,列表推导式就是生成列表的一种方法,语法是这样的:
l = [i for i in 可迭代对象]i表示要放进列表里的对象,for循环是一个式子。
比如我们用列表推导式来生成一个列表试试:
l = [i for i in range(5)]print(l)运行结果:
[0, 1, 2, 3, 4]运用列表推导式可以很方便地生成我们想要的列表。
同时它也有很多灵活的用法,比如在后面加上条件判断
l = [i for i in range(5) if 4<5]print(l)运行结果:
[0, 1, 2, 3, 4]if后面的条件判断为真,则可以正常生成列表,如果为假,则列表推导式是无效的,此时的l将是一个空列表。
还有其他灵活的用法,比如操作前面的i,比如让i的数值全都翻2倍:
我们把迭代对象换一下,换成字符串,也同样可以输出,只是*在字符串里面表示重复操作符,所以效果变成了这样:
不仅如此,前面的i*2我们还可以用函数来进行操作,比如:
总而言之,列表推导式就是用来快速和自定义生成列表的一种方法,很灵活。
那么有人可能会举一反三了,列表推导式都是用 [] 来进行操作的,那如果用()来操作行吗?它会不会生成一个元组?我们来看看:
[] 换成()之后,返回的是一个生成器generrator ,那么下面我们再来讲讲生成器:
六、生成器
生成器是真实存在于Python中的对象,与容器这种概念词是不同的,它是可以直接通过next()进行调用的。
1.生成器的第一种创建方法:生成器表达式
第一种创建方法跟列表推导式是差不多的,就是 [] 换成了():
l = (i for i in 可迭代对象)比如我们来生成一个生成器,看看能不能用next()直接调用:
l = (i for i in "abcd")print(next(l))运行结果:
a可以看出,生成器是可以直接调用的。那么既然生成器可以被next()调用,那么生成器就是一个特殊的迭代器,是一个可迭代对象。
2.生成器的第二种创建方法:yield
除了用上面那种方法创建生成器,还可以用yield来创建,方法如下:
yield 关键字比如说我们用一个函数中包含yield来创建生成器:
def fun():运行结果:a = 10
while 1:
a += 1
yield a
b = fun()print(b)
<generator object fun at 0x000001F2AD95E900>结果就是生成了一个生成器,而且此时的函数fun()就已经不再是一个函数了,它是一个生成器,只要函数中出现了yield,函数就变成了生成器。
为什么while循环没有一直执行?先不着急,我们输出看看:
def fun():运行结果:a = 10
while 1:
a += 1
yield a
b = fun()print(next(b))print(next(b))print(next(b))
111213我调用了三次,所以它就运行了三次,while循环虽然存在,但是却不起作用,是因为前面我们提过的懒汉式加载。
什么时候需要了,什么时候用next()调用,就是懒汉式加载,不像饿汉式加载那样,提前生成了所有对象,如果这里换成for循环来完成,比如:
def fun():运行之后程序将会进入死循环,一直给a自加1,你可以试试看效果,这就是饿汉式加载提前生成了迭代器并调用了全部迭代器对象,饿汉式加载占用资源的放大镜。a = 10
while 1:
a += 1
print(a)b = fun()
七、小结
今天讲的内容可能听起来比较枯燥,这也是没得办法的,有些东西第一次听可能有点”难以下咽“,见得多了之后就习惯了,你得强迫自己去试着接受和理解这些抽象的东西。最后用一张图来总结一下它们的关系:
推荐学习:python教程以上就是Python详细解析之容器、可迭代对象、迭代器以及生成器的详细内容,更多请关注盛行IT软件开发工作室其它相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。