一、生成器
任何使用 yield 的函数都称为生成器,调用生成器函数将创建一个对象(generator object),该对象通过连续调用 next() 方法生成一系列结果
next() 调用使生成器函数一直运行,到下一条 yield 语句为止,此时函数返回值赋值给 yield 语句,且函数暂时终止执行;再次调用,函数从 yield 语句之后开始执行
"""
生成器测试
"""
count = 0
def countdown(n):
global count
print("Counting down!")
while n > 0:
count += 1
print("next 语句的执行结果为前一次 yield 执行完到当前 yield 的全部执行过程 ----- next 执行次数为为 %3d" % count)
yield n
n -= 1
print("yield 语句之后的程序执行")
c = countdown(5)
print("c 的结果:", c)
# print("next 执行结果:", next(c))
# print("next 执行结果:", next(c))
# print("next 执行结果:", next(c))
next(c)
print('-' * 100)
for item in c:
print("生成器中的元素:{}".format(item))
print('-' * 100)
next(c)
c 的结果: <generator object countdown at 0x7fe07fe710a0>
Counting down!
next 语句的执行结果为前一次 yield 执行完到当前 yield 的全部执行过程 ----- next 执行次数为为 1
----------------------------------------------------------------------------------------------------
yield 语句之后的程序执行
next 语句的执行结果为前一次 yield 执行完到当前 yield 的全部执行过程 ----- next 执行次数为为 2
生成器中的元素:4
yield 语句之后的程序执行
next 语句的执行结果为前一次 yield 执行完到当前 yield 的全部执行过程 ----- next 执行次数为为 3
生成器中的元素:3
yield 语句之后的程序执行
next 语句的执行结果为前一次 yield 执行完到当前 yield 的全部执行过程 ----- next 执行次数为为 4
生成器中的元素:2
yield 语句之后的程序执行
next 语句的执行结果为前一次 yield 执行完到当前 yield 的全部执行过程 ----- next 执行次数为为 5
生成器中的元素:1
yield 语句之后的程序执行
----------------------------------------------------------------------------------------------------
Traceback (most recent call last):
File "/home/10333752@zte.intra/PycharmProjects/pythonTestProject/learning/generator.py", line 30, in <module>
next(c)
StopIteration
二、迭代器
迭代是 Python 中最强有力的特性之一,可以简单的把迭代看做是一个处理序列中元素的方式,可以使用生成器来实现简单的迭代协议
Python 的迭代协议要求 __iter__() 返回一个特殊的迭代器对象,该对象必须实现 __next__()方法,并使用 StopIteration 异常来通知迭代的完成
由于迭代器必须维护迭代过程中许多复杂的状态,因此使用生成器的方式实现迭代器可作为一个简单的实现
"""
构建一个自定义对象,利用生成器函数使其支持迭代操作
实现一个生成器,以深度优先的模式遍历树的节点
"""
import iterator_n
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)
def depth_first(self):
yield self
for c in self:
yield from c.depth_first()
# def depth_first(self):
# return iterator_n.DepthFirstIterator(self)
if __name__ == "__main__":
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))
for ch in root.depth_first():
print(ch)
"""
"""
class DepthFirstIterator(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)