zoukankan      html  css  js  c++  java
  • python 可迭代对象、迭代器、生成器

    一、可迭代对象(iterable)

    现在,我们已经获得了一个新线索,有一个叫做“可迭代的”概念

    首先,我们从报错来分析,好像之所以1234不可以for循环,是因为它不可迭代。那么如果“可迭代”,就应该可以被for循环了。

    这个我们知道呀,字符串、列表、元组、字典、集合都可以被for循环,说明他们都是可迭代的

    我们怎么来证明这一点呢?

    from collections import Iterable
                                 
    l = [1,2,3,4]                
    t = (1,2,3,4)                
    d = {1:2,3:4}                
    s = {1,2,3,4}                
                                 
    print(isinstance(l,Iterable))
    print(isinstance(t,Iterable))
    print(isinstance(d,Iterable))
    print(isinstance(s,Iterable))

    结合我们使用for循环取值的现象,再从字面上理解一下,其实迭代就是我们刚刚说的,可以将某个数据集内的数据“一个挨着一个的取出来”,就叫做迭代

    二、迭代器(iterator)

    从第一点可以看到我们常用的字符串、列表和字典都是可迭代对象,但是可迭代对象除了那些,还包括了迭代器

    结论:

    • 可迭代对象包含迭代器
    • 定义可迭代对象,必须实现__iter__()方法;定义迭代器,必须实现__iter__()和__next__()方法。

    下面以列表举个栗子,列表是可迭代对象,所以可以用__iter__()方法,查看返回值,发现该返回值也是可迭代对象,也就是说列表是可迭代对象,列表执行完__iter__()方法后也是可迭代对象,那么可以猜得到那个返回值应该就是迭代器了,然后执行__next__()方法果然可以从里面取值

    from collections import Iterable
    
    l = [1,2,3,4]
    
    l_iter = l.__iter__()
    
    print(type(l_iter))        #<class 'list_iterator'>
    print(isinstance(l,Iterable))    #true
    print(isinstance(l_iter,Iterable))    #true
    
    item = l_iter.__next__()
    print(item)        #1
    item = l_iter.__next__()
    print(item)        #2
    item = l_iter.__next__()
    print(item)        #3
    item = l_iter.__next__()
    print(item)        #4
    item = l_iter.__next__()
    print(item)        #StopIteration

    三、生成器(generator)

    生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。它不需要再像上面的类一样写__iter__()__next__()方法了,只需要一个yiled关键字。 生成器一定是迭代器(反之不成立),因此任何生成器也是以一种懒加载的模式生成值。用生成器来实现斐波那契数列的例子是:

    def fib(max):
        n, prev, curr = 0, 0, 1
        while n<max:
            yield curr
            prev, curr = curr, curr + prev
            n += 1
    
    F = fib(10)
    # print(type(F))  <class 'generator'>
    
    #第一种取值方式
    x = next(F)
    print(x)
    x = next(F)
    print(x)
    x = next(F)
    print(x)
    y = F.__next__()
    print(y)
    y = F.__next__()
    print(y)
    y = F.__next__()
    print(y)
    
    #第二种取值方式
    for _ in F:
        print(_)

    上面的命令执行后,生成1、1、2、......、55的一共10个值,第一种取值方式生成了六个值,然后就好像固定住了,第二种方式从第七个值开始取,懒加载应该就是这个意思了。

    生成器特殊的地方在于函数体中没有return关键字,函数的返回值是一个生成器对象。当执行F = fib(10)返回的是一个生成器对象,此时函数体中的代码并不会执行,只有显示或隐示地调用next或者for循环的时候才会真正执行里面的代码。

    四、生成器表达式(generator expression)

    生成器表达式是列表推倒式的生成器版本,看起来像列表推导式,但是它返回的是一个生成器对象而不是列表对象。

    a = (x for x in range(10))
    print(a)

    以及

    def fib(n):
        m, a, b = 0, 0, 1
        while m < n:
            yield b
            a, b = b, a+b
            m += 1
    
    a = (x for x in fib(10))
    print(a)
  • 相关阅读:
    108. Convert Sorted Array to Binary Search Tree
    How to check if one path is a child of another path?
    Why there is two completely different version of Reverse for List and IEnumerable?
    在Jenkins中集成Sonarqube
    如何查看sonarqube的版本 how to check the version of sonarqube
    Queue
    BFS广度优先 vs DFS深度优先 for Binary Tree
    Depth-first search and Breadth-first search 深度优先搜索和广度优先搜索
    102. Binary Tree Level Order Traversal 广度优先遍历
    How do I check if a type is a subtype OR the type of an object?
  • 原文地址:https://www.cnblogs.com/hooo-1102/p/12106325.html
Copyright © 2011-2022 走看看