zoukankan      html  css  js  c++  java
  • 迭代器和生成器

    一、手动访问迭代器中的元素

      要手动访问可迭代对象中的元素,可以使用next()函数。

    with open('/etc/passwd') as f:
        try:
            while True:
                line = next(f)
                print(line, end='')
        except StopIteration:
            pass
    
    with open('/etc/passwd') as f:
        while True:
            line = next(f,None)
            if line is None:
                break
            print(line, end='')

    二、委托迭代

      Python的迭代协议要求__iter__()返回一个特殊的迭代器对象,由该对象实现的__next__()方法来完成实际的迭代。

      如果要做的只是迭代另一个容器中的内容,我们不必担心底层细节是如何工作的,所要做的就是转发迭代请求。

    class Node:
        def __init__(self,value):
            self._value = value
            self._children = []
        
        def __repr__(self):
            return 'Node({!r})'.format(self._value)
        
        def add_children(self,node):
            self._children.append(node)
        
        def __iter__(self):
            return iter(self._children)

      __iter__()方法只是简单地将迭代请求转发给对象内部持有的_children属性上。

    四、实现迭代协议

      实现一个迭代器能够以深度优先的模式遍历树的节点

    class Node:
        def __init__(self,value):
            self._value = value
            self._children = []
    
        def __repr__(self):
            return 'Node({!r})'.format(self._value)
    
        def add_children(self,node):
            self._children.append(node)
    
        def __iter__(self):
            return iter(self._children)
    
        def depch_first(self):
            yield self
            for c in self:
                for k in  c.depch_first():
                    yield k
    
    root = Node(0)
    child1 = Node(1)
    child2 = Node(2)
    root.add_children(child1)
    root.add_children(child2)
    child1.add_children(Node(3))
    child1.add_children(Node(4))
    child2.add_children(Node(5))
    
    for ch in root.depch_first():
        print(ch)
    
    # Node(0) Node(1) Node(3) Node(4) Node(2) Node(5)

    五、定义带有额外状态的生成器函数

      如果想让生成器将状态暴露给用户,别忘了可以轻易地将其实现为一个类,然后把生成器函数的代码放到__iter__()方法中即可。

    from collections import deque
    
    class Linehistory:
        def __init__(self,lines,histlen=3):
            self.lines = lines
            self.history = deque(maxlen=histlen)
        
        def __iter__(self):
            for lineno,line in enumerate(self.lines,1):
                self.history.append((lineno,line))
                yield line
        
        def clean(self):
            self.history.clear()
    
    with open('somefile.txt') as f:
        lines = Linehistory(f)
        for line in lines:
            if 'python' in line:
                for lineno, hline in lines.history:
                    print('{}:{}'.format(lineno, hline),end='')

      使用这个类,可以将其看做是一个普通的生成器函数,但是,由于它会创建一个类实例,所以可以访问内部属性。

    十五、合并多个有序序列、再对整个有序序列进行迭代

      heapq.merge() 要求所有的输入序列都是有序的。只是简单地检查每个输入序列中的第一个元素,将最小的那个发送出去。不断重复步骤直至耗尽。

      >>> import heapq

      >>> a = [1, 4, 7, 10]

      >>> b = [2, 5, 6, 11]

      >>> for c in heapq.merge(a,b):

      ...   print(c)      # 1 2 4 5 6 7 19 11

      文件读取写入例子:

    import heapq
    
    with open('sorted_file_1','rt') as file1,
        open('sorted_file_2','rt') as file2,
        open('merged_file','wt') as outf:
        
        for line in heapq.merge(file1,file2):
            outf.write(line)

    十六、用迭代器取代while循环

      涉及I/O处理的程序中

    CHUNKSIZE = 8192
    
    def reader(s):
        while True:
            data = s.recv(CHUNKSIZE)
            if data == b''
                break
            process_data(data)

      利用iter()来替换:

    def reader(s):
        for chunk in iter(lambda :s.recv(CHUNKSIZE), b''):
            process_data(data)

      iter()会创建一个迭代器,然后重复调用用户提供的可调用对象,直到它返回哨兵值为止。   

  • 相关阅读:
    asp.net中ashx文件如何调用session
    NetAdvantage webdatagrid 控件的一些属性
    .NET 配置文件简单使用
    Dictionary的遍历和修改
    利用html+ashx实现aspx的功能
    .ashx
    jQuery AJAX实现调用页面后台方法
    用JS实现AJAX
    WCF系列学习5天速成
    介绍一个小工具 Linqer
  • 原文地址:https://www.cnblogs.com/5poi/p/11507905.html
Copyright © 2011-2022 走看看