美文网首页
关于python的可迭代对象、迭代器、生成器的理解

关于python的可迭代对象、迭代器、生成器的理解

作者: Hmcf | 来源:发表于2019-10-30 15:54 被阅读0次

    最近有朋友问到python中的迭代器和生成器的区别和作用,以及如何定义和区分,今天在这里稍微总结一下。

    可迭代对象

    定义:可迭代对象必须实现 "_iter_()" 方法。
    python中的字符串、列表、元组、字典、集合、文件对象等都是可迭代对象。

    口说无凭,上bug...不对,上法器:可使用内建函数 isinstance 来判别。

    from collections import deque
    from collections.abc import Iterable, Iterator
    
    s = "hello hmcf"
    print("string is iterable? ", isinstance(s, Iterable))
    print("string is iterator? ", isinstance(s, Iterator))
    
    l = [1, 2, 3, 4]
    print("list is iterable? ", isinstance(l, Iterable))
    print("list is iterator? ", isinstance(l, Iterator))
    
    d = {"city": "hangzhou", "age": 26}
    print("dict is iterable? ", isinstance(d, Iterable))
    print("dict is iterator? ", isinstance(d, Iterator))
    
    t = (1, "a", 2.3, [5, 6])
    print("tuple is iterable? ", isinstance(t, Iterable))
    print("tuple is iterator? ", isinstance(t, Iterator))
    
    de = deque("abcdefg")
    print("deque is iterable?", isinstance(de, Iterable))
    print("deque is iterator?", isinstance(de, Iterator))
    

    结果如下:

    string is iterable? True
    string is iterator? False
    list is iterable? True
    list is iterator? False
    dict is iterable? True
    dict is iterator? False
    tuple is iterable? True
    tuple is iterator? False
    deque is iterable? True
    deque is iterator? False

    可使用 dir() 函数来打印出来看看对象有没有_iter_方法,也可以查看 builtins.pyi 源文件找到对应方法中的定义。

    迭代器

    迭代器是在可迭代对象的基础上创建的访问集合元素的一种方式。

    迭代器是一个可以记住遍历的位置的对象。

    迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退,并且只会迭代一遍。

    迭代器对象必须同时实现 "_iter_()" 和 "_next_()" 方法才是迭代器。对于迭代器来说,"_iter_" 返回的是它自身 self,"_next_" 则是返回迭代器中的下一个值,最后没有元素时。

    字符串,列表或元组对象都可用于创建迭代器。迭代器是可迭代对象,但可迭代对象不一定是迭代器。
    迭代器的优点:每次只从对象中读取一条数据,不会造成内存的过大开销。

    至于迭代器的判断方式,在上面的可迭代对象中已经体现了。

    for循环机制

    为什么需要for循环机制?因为需要去触发、调用迭代器。字符串 、字典、列表在for循环的作用下,会生成迭代器,然后被使用。

    x = 'hello'
    for i in x:                    #iter_x=x.__iter__()
        print(i)                   #iter_x.__next__()
    iter_l =x.__iter__()           #遵循迭代器协议,生成可迭代对象
    print(iter_l.__next__())       #for循环和索引没关系 基于迭代器机制
    
    • 当对象本身就是迭代器时,For循环工作机制:

    调用 _iter_方法,返回自身self,也就是返回迭代器。不断地调用迭代器的next()方法,每次按序返回迭代器中的一个值。迭代到最后没有元素时,就抛出异常 StopIteration

    • 在可迭代对象中,for循环工作机制:

    先判断对象是否为可迭代对象(等价于判断有没有_iter_方法),没有的话直接报错,抛出TypeError异常。有的话,调用 _iter_方法,返回一个迭代器。在python内部不断地调用迭代器的_next_方法,每次按序返回迭代器中的一个值。迭代到最后没有元素时,就抛出异常 StopIteration,这个异常 python 自己会处理,不会暴露给开发者。

    生成器

    定义:边循环边计算的机制就称为生成器(generator)(对象里面不是具体的内容,而是一个产生数据的算法)

    生成器类似于返回值为数组的一个函数,这个函数可以接受参数,可以被调用,但是,不同于一般的函数会一次性返回包括了所有数值的数组,生成器一次只能产生一个值,这样消耗的内存数量将大大减小,而且允许调用函数可以很快的处理前几个返回值,因此生成器看起来像是一个函数,但是表现得却像是迭代器。

    python中生成器是迭代器的一种,可以被用作控制循环的迭代行为。

    它有两种形式:

    • 生成器函数
      使用yield返回值函数,每次调用yield会暂停,而可以使用next()函数和send()函数恢复生成器。
    import sys
     
    def fibonacci(n): # 生成器函数 - 斐波那契
        a, b, counter = 0, 1, 0
        while True:
            if (counter > n): 
                return
            yield a
            a, b = b, a + b
            counter += 1
    f = fibonacci(10) # f 是一个迭代器,由生成器返回生成
     
    while True:
        try:
            print (next(f), end=" ")
        except StopIteration:
            sys.exit()
    
    • 生成器表达式
      只要把一个列表生成式的[]中括号改为()小括号,就创建一个生成器。可以直接调用next()方法依次取出内容(取到最后会爆出错误,不优雅),另外的就是可以使用for循环来调用。
    generator = (x for x in [1,4,6,7,9] if x<5)
    for n in generator:
        print(n)
    

    相关文章

      网友评论

          本文标题:关于python的可迭代对象、迭代器、生成器的理解

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