python基础语法6-迭代器和生成器

一、迭代器
迭代就是一个重复的过程,迭代器就是在已经获得上一次结果的基础上进行的,它是一个可以记住遍历位置的对象。迭代器的作用主要是用来取值的。
在python中,列表、元组等可以使用索引进行取值,而字典、集合因为是无序的,没办法使用索引,所以就要用到迭代器来进行操作取值。

1.可迭代对象(Iterable):
python中的数据类型string、list、dict、set、tuple这些就是可迭代对象;
文件对象也是可迭代对象;还有generator(包括生成器和带yield的generator function)也是可迭代对象;
也就是可以直接作用于for循环操作的对象就是可迭代对象。
2.迭代器对象:
迭代器对象可以通过可迭代对象获得。在内置的方法中有__iter__()、__next__()的对象都是迭代器对象。
示例如下:
#coding:utf-8
import sys
s = 'string'#s是可迭代对象
#s_iter = s.__iter__()#转为迭代器对象
s_iter = iter(s)
while True:
    try:
#       print(next(s_iter))#取出迭代器对象中的值
        print(s_iter.__next__())
    except StopIteration:
        sys.exit()
注意:
迭代器对象的值被取完以后就不会再取值,如果想要重新取值,就必须重新赋值重新取。
3.可迭代对象和迭代器的区别:
所有迭代器对象都是可迭代对象,但不是所有的可迭代对象都是迭代器对象。
生成器都是迭代器对象,而list、dict、str等虽然是可迭代对象却不是迭代器对象,要变成迭代器对象是要进行转换的。
python的迭代器对象表示的是一个数据流,迭代器对象可以被next()函数调用并不断返回下一个数据,
直到没有数据时抛出StopIteration错误。可以把这个数据流看做一个有序序列,
却不知到它的长度,只能通过next()函数来不断获取下一个值,也就是迭代器的计算比较懒惰,
只有在需要的时候才会去获取数据进行处理。
如何判断是迭代器对象还是可迭代对象:可以使用isinstance()判断一个对象是否是可迭代对象,是否是迭代器对象。
示例如下:
from collections import Iterator#迭代器
from collections import Iterable#可迭代对象
s = 'string'
f = open('a.txt')
print(isinstance(s,Iterator))#结果为False
print(isinstance(s,Iterable))#结果为True
print(isinstance(f,Iterator))#结果为True
print(isinstance(f,Iterable))#结果为True
print(isinstance((i for i in range(6)),Iterable))#True
print(isinstance([1,2,3],Iterable))#True
print(isinstance({1:'a'},Iterable))#True
4.for循环机制:
for循环本质上也就是迭代器循环。
s = 'string'
for i in s:
    print(i)
工作原理:
for循环首先就是将s使用iter()方法将可迭代对象转为迭代器对象,然后再使用next()方法将得到的值给到i,
然后进行代码块的处理,逐步进行next()的取值和代码块操作,直到取完所有的值出现StopIteration错误,退出循环。
5.迭代器的优缺点:
优点:
为序列和非序列提供统一的迭代取值方法
惰性计算:不管迭代器对象有多大,同一时刻职能有一行数据存在,也就是提高开发体验和运行效率
所以在读取大文件或者无限集合的时候建议使用迭代器。
缺点:
在取的时候无法得知迭代器的长度
取值一次性,迭代器对象的值被取完以后就不会再取值,如果想要重新取值,就必须重新赋值重新取。
二、生成器
在python中使用了yield的函数被称为生成器(generator)。生成器是一个返回迭代器的函数,只能用于迭代操作。
也可以理解为生成器就是一个迭代器。
yield的作用是在函数运行中可以暂停函数的运行,并且会保存当前所有的运行信息,返回yield的值,让函数处于运行状态但不执行代码,
在下一次执行next()时从当前位置继续运行。非常有意思的是调用一个生成器函数,返回的是一个迭代器对象。
示例1:
import sys
def fib(n):#生成器
    a, b, c = 0, 1, 0
    while True:
        if c > n:
            return
        yield a
        a, b = b, a + b
        c += 1
f = fib(10)#f是迭代器,由生成器返回生成   结果为<generator object fib at 0x00B65F00>
#如果要获取其中的值,就要使用next()进行取值
'''这里值得注意的就是一定要造一个迭代器对象f,如果直接使用next()获取的话永远只能得到第一个yield的值,
它的工作原理是一直在不断生成新的生成器获得第一个yield的值'''
#print(next(fib(10)))
#print(next(fib(10)))
#print(next(fib(10)))
while True:
    try:
        print(next(f), end=' ')
    except StopIteration:
        sys.exit()
#结果为0 1 1 2 3 5 8 13 21 34 55 
示例2:使用yield实现在单线程的情况得到并发运算效果
import time
def consumer(name):
    print("%s准备学习啦!"%name)
    while True:
        lesson = yield
        print("开始[%s]上课了,[%s]老师来讲课了"%(lesson,name))
def producer():
    a = consumer('A')
    b = consumer('B')
    a.__next__()
    b.__next__()
    print("同学们开始上课了!")
    for i in range(10):
        time.sleep(1)
        print('到了两个同学!')
        a.send(i)# send的作用是唤醒并继续执行,发送一个信息到生成器内部
        b.send(i)
producer()
示例3:生成器表达式
l = [i**2 for i in range(5)]#列表
print(l)#[0, 1, 4, 9, 16]
a = (i**2 for i in range(5))#把中括号改成小括号就是生成器
print(a)#<generator object <genexpr> at 0x004C5F00>
print(list(a))#生成器转换成列表 [0, 1, 4, 9, 16]
python提供两种基本的方法:
(1).生成器函数   用def定义的函数中使用yield一次性返回一个结果,进行阻塞,重新开始
(2).生成器表达式  返回一个对象,这个对象只有在需要的时候材产生结果
yield使用的核心:
生成器是可以迭代的,但只能读取1次,只有用的时候才产生
生成器能迭代的关键是有next()方法
带有yield的函数是一个生成器,可用于迭代
yield类似return,return在生成器中代表终止,直接报错,而yield是保存当前位置的执行信息并返回值,程序再次执行时从yield保存的信息位置开始执行。
带有yield的函数不仅可以作用于for循环,还可以用于某个函数的参数,只要这个函数的参数是允许迭代的
send()和next()的区别在于send()可传递参数给yield表达式,给到yield表达式的值,而yield的参数是返回给调用者的,即send()可以强行修改上一个yield的表达式值
send()和next()都有返回值,他们的返回值是当前迭代遇到的yield的时候,yield后面表达式的值,其实就是当前迭代yield后面的参数
第一次调用时候必须先next()或send(),否则会报错,send后之所以为None是因为这时候没有上一个yield,所以也可以认为next()等同于send(None)
三、总结:
迭代既可以被写成生成器函数,也可以被协程生成器表达式,都支持自动和手动迭代,也就是说生成器的迭代器本身就是生成器本身。
迭代器不一定时生成器,生成器一定是迭代器。更多关于迭代器和生成器的学习可以参考如下网站
itertools库的学习地址:https://pymotw.com/2/itertools/
itertools库的官网地址:https://docs.python.org/2/library/itertools.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

春风抚微霞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值