python cook book第三版 读书笔记4(第四章,迭代器和生成器)

来源:互联网 发布:药房进销存软件排名 编辑:程序博客网 时间:2024/05/23 15:36

使用迭代器

4.2迭代代表,本节列举了一般在构造迭代器时候,在类里面加入__itrr__()方法

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

可以添加节点之后循环打印出来。

4.3用生成器创造新的迭代模式,使用yield关键字

>>> def frange(start,stop,increment):
...     x=start
...     while x<stop:
...             yield x
...             x+=increment
...
>>> for n in frange(0,4,0.5):
...     print n,
...
0 0.5 1.0 1.5 2.0 2.5 3.0 3.5

使用next可以依次打印里面的值

>>> c=frange(0,4,1)
>>> next(c)
0
>>> next(c)
1

4.4实现迭代协议,先看这节给出的示例代码,对比4.2多了一个depth_first的函数

class Node:
        def __init__(self,value):
                self._value=value
                self._children=[]
        def __repr__(self):
                return 'Node({0})'.format(self._value)
        def add_child(self,node):
                self._children.append(node)
        def __iter__(self):
                return iter(self._children)
        def depth_first(self):
                yield self
                for c in self:
                        yield from c.depth_first()

之后执行下面的操作

 root=Node(1)
 child1=Node(2)
 child2=Node(3)
 root.add_child(child1)
 root.add_child(child2)
 child1.add_child(Node(4))
 child1.add_child(Node(5))
 child2.add_child(Node(6))

最后打印出各节点,本节执行如下操作
 for ch in root.depth_first():
                print 'hello world'
                print(ch)

4.2节执行

 for ch in root:
                print 'hello world'
                print(ch)

对比输出结果,本节Node(1),Node(2),Node(4),Node(5),Node(3),Node(6),上节输出Node(2),Node(3)。下面作者写了一个深度优先的迭代器

>>> class DepthFirstItrrator(object):
...     def __init__(self,start_node):
...             self._node=start_node
...             self._children_iter=None
...             self._child_iter=None
...     def __iter__(self):
...             return self
...     def __next__(self):
...             if self._children_iter is None:
...                     self._children_iter=iter(self._node)
...                     return self._node
...             elif self._child_iter:
...                     try:
...                             nextchild=next(self._child_iter)
...                             return nextchild
...                     except StopIteration:
...                             self._child_iter=None
...                             return next(self)
...             else:
...                     self._child_iter=next(self._children_iter).depth_first()
...                     return next(self)

4.5使用reversed函数可以将一个序列反转。a是一个列表。

>>> for x in reversed(a):
...     print x

4.7迭代器是可以切片的,选择其中的一部分,需要import itertools,使用itertools.islice()函数。同时使用这个函数也可跳过部分循环。

4.9使用permutations可以把可能的排列打印出来,使用combinations可以把组合打印出来。

>>> items=[1,2,3]
>>> from itertools import permutations
>>> for p in permutations(items):
...     print p
...
(1, 2, 3)
(1, 3, 2)
(2, 1, 3)
(2, 3, 1)
(3, 1, 2)
(3, 2, 1)

4.10在迭代中使用enumerate函数,传入一个迭代器和开始的序号,返回序号和每此迭代的内容。

4.11本节我觉得是在使用zip函数

>>> a=[1,2,3]
>>> b=[4,5,6]
>>> list(zip(a,b))
[(1, 4), (2, 5), (3, 6)]
>>> c=[7,8,9,10]
>>> list(zip(b,c))
[(4, 7), (5, 8), (6, 9)]

这里我们可以看见c是多了一位的,但是压缩后还是只有3位,zip默认是按照短的来压缩,若想要把剩余那一位也压缩进去 需要from itertools import zip_longest函数处理。

4.12这节是在介绍itertools里面的chain函数,用于连接序列,比直接使用+更有效率

>>> from itertools import chain
>>> chain(a,b)
<itertools.chain object at 0xb733a96c>
>>> list(chain(a,b))
[1, 2, 3, 4, 5, 6]

4.13

0 0
原创粉丝点击