这里所有的答案都是伟大的,但其中只有一个答案(最受投票支持的答案)是真实的。您的代码如何工作其他涉及发电机发电机一般而言,以及它们如何运作。
所以,我不重复发电机是什么或产量是什么;我认为这些都包含在现有的答案中。然而,在花了几个小时试图理解一个与你的代码相似的代码之后,我将打破它是如何运作的。
您的代码绕过二进制树结构。 让我们以这棵树为例:
5
/ \
3 6
/ \ \
1 4 8
另一个简单的二进制搜索树的十字路口:
class Node(object):
..
def __iter__(self):
if self.has_left_child():
for child in self.left:
yield child
yield self.val
if self.has_right_child():
for child in self.right:
yield child
执行代码在Tree
对象,该对象执行__iter__
以此:
def __iter__(self):
class EmptyIter():
def next(self):
raise StopIteration
if self.root:
return self.root.__iter__()
return EmptyIter()
缩略while candidates
语句可以替换为for element in tree
; Python 翻译为
it = iter(TreeObj) # returns iter(self.root) which calls self.root.__iter__()
for element in it:
.. process element ..
因为Node.__iter__
代码里面执行时按迭代执行。 所以执行时会是这样的 :
- 根元素是第一个; 检查它是否留下了子子和
for
切换它们( 我们称它为1, 因为它的第一个迭代对象) 。
- 它有一个孩子,所以
for
执行。for child in self.left
创建 a 创建新建新迭代器调自self.left
,它是一个节点对象本身(it2)
- 和2的逻辑相同 和新的逻辑
iterator
创建(it3)
- 现在我们到达树的左边
it3
他们没有儿女,所以它是继续的,yield self.value
- 下通电话
next(it3)
它产生StopIteration
并且存在,因为它没有子女的权利(直到功能结束,没有任何成果)
it1
和it2
仍在活动----他们没有用尽,也没有召唤。next(it2)
将产生价值,而不是提高StopIteration
- 现在我们又回到
it2
和调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调- 调-next(it2)
直至它停止时:紧接着yield child
语句。由于它不再留下孩子,所以它继续并产生它self.val
.
这里的下场是 每一次迭代创建子编辑器以绕过树, 并保持当前迭代器的状态。 一旦它到达尾端, 它就会绕过堆叠, 并按正确的顺序返回值( 最低的收益率先返回 ) 。
您的代码示例在不同的技术中 做了类似的事情: 它包含一个单元素列表每个子子对每个子子子, 然后在下一个迭代中, 它弹出它, 运行当前对象的函数代码( 因此)self
).
我希望这对这个传奇话题有一点帮助,我花了好几个小时来画这个过程来理解它。