python:迭代器,生成器

可迭代对象:内部含有‘__iter__’方法的对象

优点:

存储的数据可以直接显示,比较直观

拥有的方法比较多

缺点:

占用内存

不能直接for循环取值,是通过内部转化成迭代器

# dir():获取一个对象的所有方法
s1 = ‘abcde‘
print(dir(s1))    # 输出一个list,内容是s1对象的所有方法,每个方法以字符串形式输出
print(‘__iter__‘ in dir(s1))    # 判断一个对象是否是可迭代对象

迭代器

‘‘‘
迭代器:内部含有‘__iter__‘并且含有‘__next__‘方法的对象就是迭代器
因为迭代器的内部含有‘__next__‘方法,所有可以通过for循环取值
判断一个对象是否是迭代器:‘__iter__‘ in dir(f1) and ‘__next__‘ in dir(f1)
利用iter(object)/object.__iter__()形成一个迭代器,对迭代器进行操作可以节省内存
利用next(object)/object.__next__()取值,一次只取一个
迭代就是数据处理的基石,扫描内存中放不下的数据集时,我们要找到一种惰性获取数据项的方式,即按需一次获取一个数据项,这就是迭代器模式
优点:
    节省内存
    惰性机制:next一次取一个值,下一次next再取下一个值
缺点:
    不能直观的查看里面的数据
    速度慢
    取值不能回头
‘‘‘

可迭代对象转化成迭代器

s = [11,22,33,44]
obj = s.__iter__()    # 等同于iter(s),利用s形成一个迭代器,赋值给obj
print(s)    # [11, 22, 33, 44]
print(obj)    # <list_iterator object at 0x00000000026191D0>

s = [11,22,33,44]
obj = s.__iter__()
print(obj.__next__())    # 11,等同于next(obj),迭代器利用 ‘__next__()‘方法取值,一次只取一个值
print(next(obj))        # 22
print(obj.__next__())    # 33

# 利用while循环 模拟for循环对可迭代对象取值
s  = [11,22,33,44,55,66,77,88]
obj = iter(s)
while 1:
    try:
        print(next(obj))
    except StopIteration:
        break
s  = [11,22,33,44,55,66,77,88,99]
obj = iter(s)
for i in range(4):
    print(next(obj))
for j in range(4):
    print(obj.__next__())

生成器

生成器:可以用迭代器看着是一种, 生成器的本质就是迭代器

生成是我们自己用python代码构建的数据结构,迭代器是python提供的,或者转化来的

获取生成器三种方式:

  通过生成器函数自己写

  通过生成器表达式自己写

  python内部提供

# 只要函数中有 yield,那么它就是生成器函数,一个生成器函数可以存在多个yield
# yield不会结束函数的执行,只是暂停函数
def fun():
    print(111)
    yield 3        # 一个next(),代码就会执行到这里,并且将3返回,后面的代码不执行,直到下一个next()
    print(222)
    yield 4    
ret = func() # 因为函数中有yield,所以是生成器函数,所以这里并不会执行函数中的代码
print(ret)    # <generator object fun at 0x00000000025F8570> 生成器对象
print(next(ret))    # 111 3 生成器中一个next,对应一个yield,
print(next(ret))    # 第一个yield执行完,就会执行这里的next,接着执行函数中第一个yield后面的代码
# 吃包子例子
def func():
    for i in range(1,50):
        yield f‘{i}号包子‘
ret = func()
for i in range(10):
    print(next(ret))

yield from 将一个可迭代对象变成一个生成器

def func():
    l1 = [1,2,3,4,5]
    yield l1
ret = func()  
print(ret)    # <generator object func at 0x0000000002408570>
print(next(ret))    # [1, 2, 3, 4, 5]

def func1():
    l2 = [1,2,3,4,5]
    yield from l2    # yield from 将list 变成一个生成器
ret = func1()    # 返回一个生成器对象赋值给ret
for i in ret:    # 利用for循环对生成器对象直接取值,
    print(i)
    
    
def func():
    list1 = [1,2,3,4,5]
    list2 = [6,7,8,9,0]
    yield from list1
    yield from list2
ret = func()
for i in ret:
    print(i)    # 1 2 3 4 5 6 7 8 9 0

生成器表达式 获取生成器

ret = (i for i in range(1,11))
print(ret)        # <generator object <genexpr> at 0x00000000023E8570> 
for i in ret:
    print(i)

让生成器产出值的三种方式:next(),for循环,list(),本质都是调用next()

# list(generator) ,将生成器对象转化成list
def chain(*iterables):
    for it in iterables:
        for i in it:
            yiled i
ret = chain(‘abc‘,(1,2,3))
print(ret)    # <generator object chain at 0x00000000025F8570>
print(list(ret))    # [‘a‘, ‘b‘, ‘c‘, 0, 1, 2]

def chain(*iterables):
    for it in iterables:
        yield from it
ret = chain(‘abc‘,(1,2,3))
print(list(ret))    # [‘a‘, ‘b‘, ‘c‘, 0, 1, 2]

相关推荐