• Python迭代器


    一、可迭代的对象、迭代器和生成器

    迭代是数据处理的基石。扫描内存中放不下的数据集时,我们要找到一种惰性获取数据项的方式,即按需一次获取一个数据项。这就是迭代器模式(Iterator pattern)。
    所有生成器都是迭代器,因为生成器完全实现了迭代器接口。不过,根据《设计模式:可复用面向对象软件的基础》一书的定义,迭代器用于从集合中取出
    元素;而生成器用于“凭空”生成元素。
    1、可迭代性
    """
    Sentence 类第1版:单词序列
    author:daihaolong
    2019年11月18日
    v1
    """
    import  re, reprlib
    RE_WORD = re.compile('w+')
    
    
    class Sentence:
        def __init__(self, text):
            self.text = text
            self.word = RE_WORD.findall(text)
    
        def __getitem__(self, item):
            return self.word[item]
    
        def __repr__(self):
            return "Sentence(%s)" % reprlib.repr(self.text)
    
    
    s = Sentence('"The time has come," the Walrus said,')
    print(s)
    for word in s:  # 为什么s 可迭代?因为它实现了__getitem__ 方法
        print(word)
    print(list(s))
    # **********************************************************运行结果
    Sentence('"The time ha... Walrus said,')
    The
    time
    has
    come
    the
    Walrus
    said
    ['The', 'time', 'has', 'come', 'the', 'Walrus', 'said']

    # 任何 Python 序列都可迭代的原因是,它们都实现了 __getitem__ 方法。其实,标准的序
    # 列也都实现了 __iter__ 方法,因此你也应该这么做。之所以对 __getitem__ 方法做特殊处
    # 理,是为了向后兼容,而未来可能不会再这么做

     

    解释器需要迭代对象 x 时,会自动调用 iter(x) 。
    内置的 iter 函数有以下作用。
    (1) 检查对象是否实现了 __iter__ 方法,如果实现了就调用它,获取一个迭代器。
    (2) 如果没有实现 __iter__ 方法,但是实现了 __getitem__ 方法,Python 会创建一个迭代器,尝试按顺序(从索引 0 开始)获取元素。
    (3) 如果尝试失败,Python 抛出 TypeError 异常,通常会提示“C object is not iterable”(C对象不可迭代),其中 C 是目标对象所属的类。
     
    迭代器的定义:
    迭代器是这样的对象:实现了无参数的 __next__ 方法,返回序列中的下一个元素;如果没有元素了,那么抛出 StopIteration 异常。Python 中的迭代器还实现了 __iter__ 方
    法,因此迭代器也可以迭代。
    """
    Sentence 类第2版:
    author:daihaolong
    2019年11月18日
    v2
    典型的迭代器,需要实现__iter__和__next__方法
    """
    import re, reprlib
    RE_WORD = re.compile("w+")
    
    
    class Sentence:
        def __init__(self, text):
            self.text = text
            self.words = RE_WORD.findall(text)
    
        def __iter__(self):
            return SentenceIterator(self.words)
    
        def __repr__(self):
            return "Sentence(%s)" % reprlib.repr(self.text)
    
    
    class SentenceIterator:
        def __init__(self, words):
            self.index = 0
            self.words = words
    
        def __iter__(self):
            return self
    
        def __next__(self):
            try:
                word = self.words[self.index]
            except IndexError:
                raise StopIteration()
            self.index += 1
            return word
    
    
    s = Sentence('"The time has come," the Walrus said,')
    print(s)
    for word in s:  # 为什么s 可迭代?因为它实现了__getitem__ 方法
        print(word)
    print(list(s))
    

      

    3、生成器
    只要 Python 函数的定义体中有 yield 关键字,该函数就是生成器函数。调用生成器函数时,会返回一个生成器对象。也就是说,生成器函数是生成器工厂。
    """
    Sentence 类第3版:
    author:daihaolong
    2019年11月18日
    v3
    典型的迭代器,需要实现__iter__和__next__方法
    """
    import re, reprlib
    RE_WORD = re.compile("w+")
    
    
    class Sentence:
        def __init__(self, text):
            self.text = text
            self.words = RE_WORD.findall(text)
    
        def __iter__(self):
            for word in self.words:
                yield word
            return
    
        def __repr__(self):
            return "Sentence(%s)" % reprlib.repr(self.text)
    
    
    s = Sentence('"The time has come," the Walrus said,')
    print(s)
    for word1 in s:  # 为什么s 可迭代?因为它实现了__getitem__ 方法
        print(word1)
    print(list(s))
    

      

    惰性实现版
    1)yield生成器版
    """
    Sentence 类第4版:
    author:daihaolong
    2019年11月18日
    v4
    使用惰性版本
    """
    import re, reprlib
    RE_WORD = re.compile('w+')
    
    
    class Sentence:
        def __init__(self, text):
            self.text = text
    
        def __repr__(self):
            return "Sentence(%s)" % reprlib.repr(self.text)
    
        def __iter__(self):
            for word in RE_WORD.finditer(self.text):  # 这样就是惰性的,不用一下生产一个列表
                yield word.group()
    
    
    s = Sentence('"The time has come," the Walrus said,')
    print(s)
    for word1 in s:  # 为什么s 可迭代?因为它实现了__getitem__ 方法
        print(word1)
    print(list(s))
    

      

    2)生成器表达式版
    """
    Sentence 类第5版:
    author:daihaolong
    2019年11月18日
    v5
    使用惰性版本
    """
    import re, reprlib
    RE_WORD = re.compile('w+')
    
    
    class Sentence:
        def __init__(self, text):
            self.text = text
    
        def __repr__(self):
            return "Sentence(%s)" % reprlib.repr(self.text)
    
        def __iter__(self): # 直接使用列表生成式,带括号的其实就是生成器
            return (word.group() for word in RE_WORD.finditer(self.text))
    
    
    s = Sentence('"The time has come," the Walrus said,')
    print(s)
    for word1 in s:  # 为什么s 可迭代?因为它实现了__getitem__ 方法
        print(word1)
    print(list(s))
    

      

     

    Nobody knows it better than me.
  • 相关阅读:
    力扣236题、235(二叉树最近公共祖先)
    力扣222题(完全二叉树的节点个数)
    力扣130题、990题(并查集算法)
    力扣855题(考场就座)
    力扣659题(分割数组为连续子数组)
    力扣435题(区间调度问题)
    【转】编程之:EXPORT_SYMBOL使用
    【转】shell工具之:常用shell脚本命令详细
    【转】vim工具命令之:添加行号和删除行号
    BUG之【虚拟机报错】:Centos出现 rm: cannot remove x: Read-only file system 的总结
  • 原文地址:https://www.cnblogs.com/dadaizi/p/11964749.html
Copyright © 2020-2023  润新知