我们来看下yield在类中的应用。代码如下:
class Node:
def __init__(self,value):
self._value=value
self._child=[]
def __repr__(self):
return "Node%s" % self._value
def add_child(self,node):
self._child.append(node)
def __iter__(self):
return iter(self._child)
def depth_first(self):
yield self
for c in self:
yield c
for last in c:
yield last
def iter_function():
root=Node(0)
child1=Node(1)
child2=Node(2)
root.add_child(child1)
root.add_child(child2)
child1.add_child(Node(3))
child1.add_child(Node(4))
child2.add_child(Node(5))
child2.add_child(Node(6))
for ch in root.depth_first():
print ch
在iter_function1中root是根节点。下面有child1和child2 2个子节点。其中child1和child2下面各自有3,4/5,6节点。我们做要实现一个节点的深度遍历。期望得到的结果是Node0,Node1,Node3,Node4,Node2,Node5,Node6.在depth_first中用到了3个yield语句。其中yield self是返回当前的根节点。yield c是返回根节点下的子节点. yield last是继续在上一步的基础上返回上一层的子节点。由于在__iter__中返回的是_child的迭代对象。因此上面的功能也就是不停地遍历各个节点下的_child对象。
执行结果如下:和我们预想的结果一致
我们来看下单步调试的结果:
首先进入Node0节点
打印出Node0
开始遍历Node0的子节点,第一个是Node1
此时ch=Node1
打印出Node1
接着遍历Node1的子节点。第一个是Node3
Ch=Node3
打印出Node3
Node1的下一个子节点Node4
打印出Node4
Node1遍历完后,开始遍历Node2
首先打印出Node2
开始遍历node2,第一个子节点是node5
最后一个是node6
反向遍历列表。有一个列表a=[1,2,3,4].想从列表末尾开始遍历。可以用reversed 来实现这个效果
a=[1,2,3,4]
for x in reversed(a):
print x
发现迭代只有在对象实现了__reversed__方法且对象大小是确定的情况下才起作用。如果不符合上述条件,必须先将对象转换成列表。
我们可以自定义__reversed__来实现反向迭代。
class CountDown():
def __init__(self,start):
self.start=start
def __iter__(self):
n=self.start
while n > 0:
yield n
n-=1
def __reversed__(self):
n=1
while n<=self.start:
yield n
n+=1
for x in CountDown(5):
print x
print 'reversed result:\n'
for x in reversed(CountDown(5)):
print x
结果如下:
迭代器切片:
假设有如下的代码,count函数实现从n开始的加一操作
def count(n):
while True:
yield n
n+=1
for c in count(5):
print c
当开始遍历的时候。会一直打印从5开始的加一结果。但是我们只是想得到其中一部分的结果。比如第10到15个生成结果
c=count(<span lang="EN-US" style="" color:"="">5)
print c[10:15]
报如下错误,无法进行数据切片
如果要对生成器进行切片,要用到itertools.islice功能,代码改造如下:
c=count(5)
for x in itertools.islice(c,10,15):
print x
结果如下,得到了我们想要的结果