美文网首页
(5) python 迭代器和生成器

(5) python 迭代器和生成器

作者: 小黄不头秃 | 来源:发表于2022-10-20 00:22 被阅读0次

(一)迭代器

迭代器是一种对象,该对象包含值的可计数数字。
迭代器是可迭代的对象,这意味着您可以遍历所有值。

从技术上讲,在 Python 中,迭代器是实现迭代器协议的对象,它包含方法 iter() 和 next()。

列表、元组、字典和集合都是可迭代的对象。它们是可迭代的容器,您可以从中获取迭代器(Iterator)。

所有这些对象都有用于获取迭代器的 iter() 方法:
也可以使用for循环,循环遍历可迭代对象。
当迭代器已经将可迭代对象里面的数据都读取完了,你再使用next方法就会报错StopIteration。

如果一个对象实现了__iter__方法,那么它就是一个可迭代对象。
如果一个对象实现了__iter____next__方法,那么它就是一个迭代器。

list1 = [1,2,3,4,5]
str1 = "abcdefg"
it1 = iter(list1)
it2 = iter(str1)
print(next(it1)) # 1
print(next(it2)) # a

for i in it1:
    print(i) # 2 3 4 5

print(next(it1)) # StopIteration:
# 自定义迭代器
class MyNumber:
    def __init__(self,start=0, value=0, step=1) -> None:
        if start > value:
            raise Exception("开始值不能大于结束值!")
        self.value = value 
        self.step = step
        self.start = start

    def __iter__(self):
        self.index  =  self.start
        self.x = None
        return self # 必须要返回迭代器对象本身

    def __next__(self):
        if self.index < self.value:
            self.x = self.index
            self.index += self.step
            return self.x
        else:
            # print("结束了")
            raise StopIteration

for i in MyNumber(-5,5,2): # 创建了一个类似range类的MyNumber类
    print(i)

# 等同于
for i in range(-5,5,2): # 左闭右开[-5, 5)
    print(i)

所以根据上面的代码我们可以得出for循环的工作流程。

  1. 调用该对象的iter方法获取迭代器
  2. 调用next方法,获取迭代值
  3. 捕获StopIteration异常,结束循环
  4. 执行for循环里的代码

生成器

其实生成器也是一种迭代器,但是它是一种特殊的迭代器。他的功能是,我们每调用一次就会返回一个值,这个值是调用的时候生成的,并不是提前准备好的。

(1)二者区别

1.迭代器是访问容器的一种方式,也就是说容器已经出现。我们是从已有元素拓印出一份副本,只为我们此次迭代使用。而生成器则是,而生成器则是自己生成元素的。也就是前者是从有到有的复制,而后者则是从无到有的生成。以 list 容器为例,在使用该容器迭代一组数据时,必须事先将所有数据存储到容器中,才能开始迭代;而生成器却不同,它可以实现在迭代的同时生成元素。

2.在用法上生成器只需要简单函数写法,配合yield就能实现。而迭代器真正开发中很难使用到。我们可以把生成器看做,python给我们提供的特殊接口实现的迭代器。

(2)如何定义一个生成器

不仅如此,生成器的创建方式也比迭代器简单很多,大体分为以下 2 步:

  1. 定义一个以 yield 关键字标识返回值的函数;
  2. 调用刚刚创建的函数,即可创建一个生成器;

下面的代码分别使用生成器实现range和zip的功能。

def generators(start=0, value=0, step=0):
    if start > value:
        raise Exception("开始值不能大于结束值!")
    while start < value:
        yield start
        start = start+step

for i in generators(-5,5,2):
    print(i)
list1 = ["a","b","c"]
list2 = [1,2,3,4]

def my_zip(*lists):
    min_len = min([len(l) for l in lists])
    index=0
    while min_len:
        yield tuple([x[index] for x in lists])
        index+=1
        min_len-=1

dict1 = {}
for x,y in my_zip(list1,list2):
    dict1[x] = y

print(dict1) # {'a': 1, 'b': 2, 'c': 3}

相关文章

网友评论

      本文标题:(5) python 迭代器和生成器

      本文链接:https://www.haomeiwen.com/subject/xnhyartx.html