pythonfor循环是迭代器吗_15.python的for循环与迭代器、生成器

在前面学习讲完while循环之后,现在终于要将for循环这个坑填上了。之所以拖到现在是因为for循环对前面讲过的序列、字典、集合都是有效的,讲完前面的内容再来讲for循环会更加容易上手。

首先,for循环和while循环一样,都是在满足一定条件的时候对其内层的代码进行循环执行。不同的是,while循环判断的是条件,而for判断的是迭代对象。

Python 中的 for 接受可迭代对象(例如序列或迭代器)作为其参数,每次迭代其中一个元素。

我们先来看for循环的代码:

a = (1, 2, 3, 4, 5)for x ina:print x

我们以序列中的元祖为例,发现其输出了这些,那么这段代码的逻辑是怎么样的?为了方便大家理解,我画了这样一个图:

我写了一个收租的小故事,方便大家理解。不知道为什么写的时候感觉眼角有点湿润。

for循环其实就是不断的去可迭代对象中拿去元素,而可迭代对象在每次迭代的时候都会把指针下移一格,也就是下次再来拿的时候,拿的是下一个。而这是因为可迭代对象有这样行为,才称其为可迭代。

这个时候我又要问一个问题,在迭代循环结束以后,x的值是否还存在?

当然还在,都说了作用域是函数的东西,迭代循环并不是函数。按照for循环的思路,x的值是不断更新的,所以在循环结束的时候,x应该等于最后一次迭代的值。以这里为例,x在循环结束的时候,其值应该为5。即x=5。

a = (1, 2, 3, 4, 5)for x ina:printxprint '----',xprint a

另外,虽说交租是交了出去自己没有了,但是迭代循环并不会改变a本身,也就是相当于借给别人看一眼,东西还是自己的。

当然现实中没有这样的福利就是了。

序列的迭代都和上面的一样,其都是按照索引的顺序依次给出。而字典和集合都是无序的,所以循环得到的顺序和我们代码写的顺序是不同的。但是我在字典篇中说过,字典的无序体现在其保存上,也就是一旦保存以后,其顺序虽然和我们代码写的顺序不同,但也不会每次循环得到的顺序都不同。如果每次循环得到的顺序都不同那要多大工程,浪费多少计算资源,这显然不符合python化繁为简的哲学。

另外,这里提醒一句,字典循环得到的键,而集合没有键的概念,所以得到的元素。

1.迭代器和生成器

你可能会看到这样的写法:

for x in range(1,5):print x

range()是什么鬼,我们先进交换模式看一下先:

直接返回了一个列表,也就是这个函数是快速生产列表的咯,for循环就相当于迭代了列表了咯,这就好理解了。

还可能会有这个写法:

for x in xrange(1,5):print x

xrange()又是什么鬼?

返回了自己。

好吧,这里解释一下,什么是迭代器和生成器了。

1.迭代器

迭代器是一个实现了迭代器协议的对象,Python中的迭代器协议就是有next方法的对象会前进到下一结果,而在一系列结果的末尾是,则会引发StopIteration。

而在for循环中,会自动调用 iter()将我们要迭代的对象转化为可迭代对象,每次循环都会调用 .next() 方法获取新元素,当引发StopIteration错误的时候自动退出循环,这就for循环的内部操作。

常用的数据类型,如:str、tuple、list、dict、set,都能进行迭代循环,因为其内部都有相应的方法,如list中的:

所以我们自己也可以创建一个可迭代的类:

classText():def __init__(self,list_input): #初始化函数

self.list =list_input

self.i=0def __iter__(self):returnselfdefnext(self):if self.i == len(self.list): #如果索引到了最后,说明迭代完毕

self.i = 0 #将索引归0

raise StopIteration #触发错误

#如果索引没到最后

self.i += 1 #索引先后移一位

return self.list[self.i - 1] #取出前一位的值

a = Text([1,2,3])for x ina:print x

这就是迭代器了。

2.生成器

xrange()就是生成器。

所谓的生成器就是每次调用的时候返回一个对象,而不是一次性在内存中创建,从而达到节约内存的作用。

而生成器靠yield关键字实现,生成器的编写类似于函数,只不过将函数的return改成了yield:

defscq():yield 1

yield 2

yield 3a=scq()printa.next()printa.next()print a.next()

每次调用a.next()的时候得到的都是不同的值。

当然我们也可以像函数一样处理它:

总之,yield的核心在于冻结函数,一旦遇到,冻结这个函数;而return在于结束函数,一旦遇到,返回结果,函数整个退出,下次调用时重新开始执行。

当然,到了最后一个的时候也会触发错误:

可以看出,生成器是每次调用的时候生成一个对象,所以生成器比迭代器更节约内存,但也更耗费cpu,因为代码需要运算。不过一般情况下,使用生成器会有更高的效率。

最后补充range和xrange两个函数的用法:

range和xrange都接受三个参数:

其中start和stop表示开始和结束,同样不包括结束的那个值,后面的只是个分界线而已。当只给一个参数的时候,默认从0开始,即start=0。

而step表示步长,和序列中的一样,表示走几步执行生成一次。

暂时先写这么多,后面有什么错误和补充的会继续完善。

参考和转载的文献:戳这里

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值