zoukankan      html  css  js  c++  java
  • CP学习笔记(9)

    Python中自定义迭代类型,需要包含自定义的__next__方法。__next__方法能够返回迭代类型的下一项,并在迭代结束时提示编译器:StopIteration

    # define a new iteration class
    >>> class LetterIter:
            """An iterator over letters of the alphabet in ASCII order."""
            def __init__(self, start='a', end='e'):
                self.next_letter = start
                self.end = end
            def __next__(self):
                if self.next_letter == self.end:
                    raise StopIteration
                letter = self.next_letter
                self.next_letter = chr(ord(letter)+1)
                return letter
               
    # init a object of defined iteration class
    >>> letter_iter = LetterIter()
    >>> letter_iter.__next__()
    'a'
    >>> letter_iter.__next__()
    'b'
    >>> next(letter_iter)
    'c'
    >>> letter_iter.__next__()
    'd'
    >>> letter_iter.__next__()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 12, in next
    StopIteration
    

    如果一个对象的__iter__方法被调用后能够返回一个迭代对象,那么这个对象就是可迭代(iterable)。

    >>> class Letters:
            def __init__(self, start='a', end='e'):
                self.start = start
                self.end = end
            def __iter__(self):
                return LetterIter(self.start, self.end)
    
    >>> b_to_k = Letters('b', 'k')
    >>> first_iterator = b_to_k.__iter__()
    >>> next(first_iterator)
    'b'
    >>> next(first_iterator)
    'c'
    >>> second_iterator = iter(b_to_k)
    >>> second_iterator.__next__()
    'b'
    >>> first_iterator.__next__()
    'd'
    >>> first_iterator.__next__()
    'e'
    >>> second_iterator.__next__()
    'c'
    >>> second_iterator.__next__()
    'd'
    
    

    for语句也可以用于列举。

    for <name> in <expression>:
        <suite>
    

    编译器首先会检查<expression>是否是可迭代对象,然后调用__iter__方法。编译器会反复调用__next__方法直至遇到StopIteration。每次调用__next__方法,编译器都会把得到的值绑定在<name>上,然后执行<suite>语句。下面两个示例是等价的。

    >>> counts = [1, 2, 3]
    >>> for item in counts:
            print(item)
    1
    2
    3
    
    >>> items = counts.__iter__()
    >>> try:
            while True:
                item = items.__next__()
                print(item)
        except StopIteration:
            pass
    1
    2
    3
    

    Python官网文档Iterator types一章建议迭代对象的__iter__方法最好返回迭代对象本身,这样所有迭代对象都是可迭代的。

    __next__方法只能用于列举简单的迭代对象,对于复杂的迭代对象需要用到generator迭代类型。不同的是,generator迭代类型不使用return返回值,而是用yield语句。

    如何理解Python关键字yield:

    当函数被调用时,函数体中的代码是不会运行的,函数仅仅是返回一个生成器对象。这里理解起来可能稍微有点复杂。函数中的代码每次会在for循环中被执行,接下来是最难的一部分:
    for第一次调用生成器对象时,代码将会从函数的开始处运行直到遇到yield为止,然后返回此次循环的第一个值,接着循环地执行函数体,返回下一个值,直到没有值返回为止。
    一旦函数运行再也没有遇到yield时,生成器就被认为是空的。

    >>> def letters_generator():
            current = 'a'
            while current <= 'd':
                yield current
                current = chr(ord(current)+1)
    >>> for letter in letters_generator():
            print(letter)
    a
    b
    c
    d
    
    >>> letters = letters_generator()
    >>> type(letters)
    <class 'generator'>
    >>> letters.__next__()
    'a'
    >>> letters.__next__()
    'b'
    >>> letters.__next__()
    'c'
    >>> letters.__next__()
    'd'
    >>> letters.__next__()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    StopIteration
    

    Python中还有Streams类可以返回数据序列。Streams实例是懒惰计算(Lazyily Computed)的。

    >>> class Stream:
            """A lazily computed linked list."""
            class empty:
                def __repr__(self):
                    return 'Stream.empty'
            empty = empty()
            def __init__(self, first, compute_rest=lambda: empty):
                assert callable(compute_rest), 'compute_rest must be callable.'
                self.first = first
                self._compute_rest = compute_rest
            @property
            def rest(self):
                """Return the rest of the stream, computing it if necessary."""
                if self._compute_rest is not None:
                    self._rest = self._compute_rest()
                    self._compute_rest = None
                return self._rest
            def __repr__(self):
                return 'Stream({0}, <...>)'.format(repr(self.first))
    

    Streams实例返回两项:first 和 rest。每次返回值时只计算first,不计算rest。

    >>> r = Link(1, Link(2+3, Link(9)))
    
    >>> s = Stream(1, lambda: Stream(2+3, lambda: Stream(9)))
    
    >>> r.first
    1
    >>> s.first
    1
    >>> r.rest.first
    5
    >>> s.rest.first
    5
    >>> r.rest
    Link(5, Link(9))
    >>> s.rest
    Stream(5, <...>) # rest项为None,并没有被计算出来
    
  • 相关阅读:
    nginx显示中文乱码
    Job for mariadb.service failed because the control process exited with error code. See "systemctl status mariadb.service" and "journalctl -xe" for details
    linux 7 网卡配置
    zabbix 离线安装
    linux alias 设置命令别名
    重启redis shell脚本
    docker离线安装
    ansible 批量添加用户
    linux 7 离线安装ansible
    Linux 7 配置163yum源
  • 原文地址:https://www.cnblogs.com/rim99/p/5058868.html
Copyright © 2011-2022 走看看