迭代器和生成器

迭代

通过for遍历访问一个列表或者容器里的所有元素,这个遍历我们就可以称之为迭代。

可以被for循环的都是可迭代的类型,可迭代类型内部一定有__iter__方法。

迭代器

每个可迭代对象内部都有__iter__方法,当可迭代对象执行了__iter__方法就成了一个迭代器

print([1, 2, 3].__iter__())

# 结果 <list_iterator object at 0x7f21fbd581d0

 我们利用dir 来查看下迭代器 和可迭代对象之间有什么不同的方法

list1 = [1, 2, 3, 4, 5]
iter1 = list1.__iter__()
print(set(dir(iter1)) - set(dir(list1)))

# 结果 {'__length_hint__', '__setstate__', '__next__'}

可以看到 迭代器 比 可迭代对象多了三个方法

# 查看迭代器内共有多少元素
print(iter1.__length_hint__())

# 指定迭代器从第几个元素开始迭代
iter1.__setstate__(2)
for i in iter1:
    print(i)

# 从迭代器中取下一个值
print(iter1.__next__())
print(iter1.__next__())
print(iter1.__next__())

 注意:next方法会如果一直取值,当迭代器没有值可以取的时候,会抛出一个异常StopIteration,异常处理如下

while True:
    try:
        print(iter1.__next__())
    except StopIteration:
        break

range()方法是什么类型

print("__iter__" in dir(range(1, 10)))  # True
print("__next__" in dir(range(1, 10)))  # False

可以看出range内有iter方法,但是没有next方法,由此,range方法得到的是一个可迭代对象,而不是一个迭代器

from collections import Iterator

print(isinstance(range(100000000), Iterator))  # 验证range执行之后得到的结果不是一个迭代器

 

生成器

迭代器的功能就是节省内存,为了实现这一功能,有的时候我们需要自己定义一个迭代器,我们自己定义的这个具有迭代器功能的就是生成器

实现:和函数定义一样,不同的是使用yeild语句返回结果而不是return,yield一次返回一个结果,返回之后挂起函数状态,下一次执行从该处继续执行,

  可以说一个包含了yield关键子的函数就是生成器,调用生成器函数会返回一个生成器对象

用生成器写一个range()

def my_range(start, stop, step):
    n = start
    while n < stop:
        yield n
        n += step


for i in my_range(1, 100, 3):
    print(i)

 

posted @ 2019-07-26 09:36  南头老李  阅读(120)  评论(0编辑  收藏  举报