迭代器与生成器

迭代器与生成器

一 迭代器 iterator

1 什么是迭代器?(迭代与迭代器)

-器:指的就是工具。

-迭代:是一个重复的过程,但每次重复都是基于上次的结果而来的。

-迭代器:指的是一种不依赖于索引取值的工具。
# 索引取值
names = ['zhangsan','lisi','wangwu']
count = 0
while count < len(names):
    print(names[count])
	count += 1

2 为何要有迭代器

2.1 迭代器的两个特性

(1) 迭代器是一种不依赖索引取值的工具;

(2) 惰性计算,节省内存。

3 如何使用迭代器

3.1 引入,以字典为例:

dic = {'name':'zhangsan','age':18,'gender':'male'}
dic_iterator = dic.__iter__()
# 一般方法
res1 = dic_iterator.__next__()
print(res1)  # 'zhangsan'
res2 = dic_iterator.__next__()
print(res2)  # 18
res3 = dic_iterator.__next__()
print(res3)  # 'male'

dic_iterator.__next__()  # StopIteration

# 使用循环+try语句,可以捕捉异常,使循环及时结束。
while True:
    try:
        res = dic_iterator.__next__()
        print(res)
    except StopIteration:
        break

3.2 可迭代对象与迭代器对象

3.2.1 可迭代对象
-内置有 __iter__ 方法的数据类型称之为:可迭代对象/类型。 如:字典dictionary、集合set、列表list、字符串string、元组tuple、文件对象file(也是迭代器对象) 。
3.2.2 迭代器对象
-内置有 __next__ 方法与 __iter__ 方法的数据类型称之为:迭代器对象。
dic = {'name':'zhangsan','age':18,'gender':'male'}

dic_iterator1.__iter__()
dic_iterator1.__next__()

print(dic_iterator1.__iter__().__iter__().__iter__() is dic_iterator1)  # True
print(dic_iterator2)  # <dict_keyiterator object at 0x00000245D0ECD090>
3.2.2.1 为何迭代器对象同时内置了 __next__方法与__iter__方法?
    1)-迭代器的创造是为了方便for循环取值,由于for循环取值使用频率很高,所以for k in iterator中,iterator每次都调用 __iter__ 的方法,将可迭代对象直接变为迭代器对象,不进行额外的判断,可以提高效率,所以迭代器对象同时具有了以上两个方法,是为了真正的节省内存。
    2)-文件对象由于可能会很大,所以同时具有 __next__ 方法与 __iter__ 方法,以节省内存。
3.2.3 总结:
-迭代器对象一定是可迭代对象,可迭代对象不一定是迭代器对象。

3.3 for循环的工作原理

dic = {'name':'zhangsan','age':18,'gender':'male'}dic_iterator = dic.__iter__()while True:    try:        res = dic_iterator.__next__()        print(res)    except StopIteration:        break        for k in dic:    print(k)    """步骤1 先让dic调用__iter__()方法,dic_iterator = dic.__iter__();步骤2 k=dic_iterator.__next__(),执行循环体代码;步骤3 循环往复,直到抛出异常,for循环会帮我们捕捉异常结束循环。"""for k in dic_iterator:  # 与上面for k in dic 得出的结果一样    print(k)

3.4 基于同一个迭代器重复取值

# 基于同一个迭代器取值,最终会将迭代器的值取尽,重新开始一个新的迭代取值过程,可以重新制造一个迭代器,再次进行迭代取值。

二 生成器 generator

1 什么是生成器

-但凡是函数内出现了yield关键字,调用函数将不会执行函数体代码,会得到一个返回值,该返回值就是我们自定义的迭代器,称之为生成器。# 生成器的唯一注意事项就是:生成器只能遍历一次。
def func():    print('hello1')    yield 111  # 执行到yield会暂停并返回一个值。    print('hello2')    yield 222    print('hello3')    yield 333g = func()print(g)  # 生成器本质就是迭代器  <generator object func at 0x0000025CA029F2E0>res = next(g)print(res)  # hello1            # 111res = next(g)print(res)  # hello2            # 222res = next(g)print(res)  # hello3            # 222next(g)  # StopIteration

2 yield与return的异同点

### 1.相同点:    都可以用来返回值。### 2.不同点:    return只能返回一次值,函数就会立即结束。    yield可以用于返回多次值,可以挂起函数。
# 案例:使用yield无限取值,每次内存只有一个值。def func():     res=0     while True:         res+=1         yield resg=func()for i in g:    print(i)
# 实现一个自定义的range功能:def my_range(start, stop, step=1):    while stop > start:        yield start        start += stepfor i in my_range(1,3,1):    print(i)  # 1 2print(type(my_range))  # <class 'function'>print(type(my_range(1,3,1)))  # <class 'generator'>

3 总结迭代器的优点与缺点

### 1.优点:    (1) 是一种通用的迭代取值方案;    (2) 惰性计算,以节省内存。### 2.缺点:    (1) 取值不如索引、key的取值方式灵活;    (2) 取值是一次性的,只能往后取,不能预估值的个数。
posted @ 2020-03-12 21:57  越关山  阅读(235)  评论(0)    收藏  举报