Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
这种基于Python生成器的顺序遍历方法的工作原理_Python - Fatal编程技术网

这种基于Python生成器的顺序遍历方法的工作原理

这种基于Python生成器的顺序遍历方法的工作原理,python,Python,我对python还很陌生,还在探索。遇到生成器,下面是使用生成器实现有序二叉树遍历的代码段: def inorder(t): if t: for x in inorder(t.left): yield x yield t.label for x in inorder(t.right): yield x 现在我知道了关于生成器的以下事实:它们记住调用中的局部变量值。然而,这个函数是递归的。

我对python还很陌生,还在探索。遇到生成器,下面是使用生成器实现有序二叉树遍历的代码段:

def inorder(t):
    if t:
        for x in inorder(t.left):
            yield x

        yield t.label

        for x in inorder(t.right):
            yield x
现在我知道了关于生成器的以下事实:它们记住调用中的局部变量值。然而,这个函数是递归的。那么它如何在这些不同的递归调用中记住局部变量值呢


另外,很容易理解正常的递归顺序程序(不涉及生成器),因为有明确指定的递归终止条件。但是这种使用生成器的递归是如何工作的呢?

按顺序返回生成器。该对象在调用
next
之间记住其本地状态。通过单独调用顺序
创建的生成器之间没有重叠,即使递归调用也是如此。

我对代码进行了一些修改,以了解执行序列的流程。基本上我添加了一些
print()
语句

class BinaryTreeNode():
    def __init__(self, pLeft, pRight, pValue):
        self.left = pLeft
        self.right = pRight
        self.label = pValue

def inorder(t):
    print("at the beginning of inorder(t): " + (str(t.label) if t else "None" ))
    if t:
        for x in inorder(t.left):
            print("inside inorder(t.left):" + str(t.label))   #delete
            yield x

        print("inside inorder(t):" + str(t.label))   #delete
        yield t.label

        for x in inorder(t.right):
            print("inside inorder(t.right):" + str(t.label))  #delete
            yield x

node1 = BinaryTreeNode(None,None,1)
node3 = BinaryTreeNode(None,None,3)
node2 = BinaryTreeNode(node1,node3,2)
node5 = BinaryTreeNode(None,None,5)
node4 = BinaryTreeNode(node2,node5,4)

root = node4

for i in inorder(root):
    print(i)
输出为:

1    at the beginning of inorder(t): 4
2    at the beginning of inorder(t): 2
3    at the beginning of inorder(t): 1
4    at the beginning of inorder(t): None
5    inside inorder(t):1
6    inside inorder(t.left):2
7    inside inorder(t.left):4
8    1
9    at the beginning of inorder(t): None
10    inside inorder(t):2
11    inside inorder(t.left):4
12    2
13    at the beginning of inorder(t): 3
14    at the beginning of inorder(t): None
15    inside inorder(t):3
16    inside inorder(t.right):2
17    inside inorder(t.left):4
18    3
19    at the beginning of inorder(t): None
20    inside inorder(t):4
21    4
22    at the beginning of inorder(t): 5
23    at the beginning of inorder(t): None
24    inside inorder(t):5
25    inside inorder(t.right):4
26    5
27    at the beginning of inorder(t): None
请注意,对inorder(node4)
的第二次调用没有在inorder(t):4的开头打印
,而是在inorder(t)的开头打印
:None
(输出中的第9行)。这意味着生成器还记得最后执行的行(主要是因为它记得最后一次调用中的程序计数器值)

此外,每个for循环都从函数
inoorder()
获取生成器实例。该生成器特定于for循环,因此本地范围是单独维护的

上面横穿了这棵树:

    4
   / \
  2   5
 / \
1   3
当每个递归调用到达其结束时,也会发生终止。这将导致以下递归调用树:

==>inorder(<4>) 
   |---> x in inorder(left<2>)
                 |---> x in inorder(left<1>)
                               |---> x in inorder(left<None>) --> terminate
                                    yield 1   (note the indention, it is not yield inside first for-in loop but after it)
                            yield 1  (note the indentation, this is yield inside first for-in loop)
              yield 1



inorder(<4>)
   |---> x in inorder(left<2>)
                 |---> x in inorder(left<1>)        
==============================>|---> x in inorder(right<None>) --> terminate
                      yield 2
              yield 2



inorder(<4>)
   |---> x in inorder(left<2>)
================>|---> x in inorder(right<3>)                                                      
                               |---> x in inorder(left<None>) --> terminate
                                     yield 3  
                            yield 3
              yield 3     



inorder(<4>)
  |---> x in inorder(left<2>)
                |---> x in inorder(left<1>)        
=============================>|---> x in inorder(right<None>) --> terminate
                      terminate
             terminate
        yield 4



inorder(4)
==>|---> x in inorder(right<5>)
                 |---> x in inorder(left<None>) --> terminate
                       yield 5 
              yield 5


inorder(4)
   |---> x in inorder(right<5>)                 
===============>|---> x in inorder(right<None>) --> terminate
                      terminate
              terminate
         terminate
==>顺序()
|--->顺序中的x(左)
|--->顺序中的x(左)
|--->顺序中的x(左)->终止
收益率1(注意缩进,它不是循环内第一个收益率,而是循环后的收益率)
屈服1(注意压痕,这是回路中第一个内部屈服)
收益率1
顺序()
|--->顺序中的x(左)
|--->顺序中的x(左)
==================================>|-->顺序中的x(右)-->终止
收益率2
收益率2
顺序()
|--->顺序中的x(左)
=============>|-->按顺序输入x(右)
|--->顺序中的x(左)->终止
收益率3
收益率3
收益率3
顺序()
|--->顺序中的x(左)
|--->顺序中的x(左)
==================================>|-->顺序中的x(右)-->终止
终止
终止
收益率4
顺序(4)
==>|-->x按顺序排列(右)
|--->顺序中的x(左)->终止
收益率5
收益率5
顺序(4)
|--->顺序中的x(右)
================>|-->顺序中的x(右)-->终止
终止
终止
终止
(解释:

  • 表示以
    nodei
    为参数的调用
  • left
    表示
    inoder(t.left)
    t.left
    nodei
  • right
    表示
    inoder(t.right)
    t.right
    nodei
  • ==>
    显示在该特定调用中执行从何处开始)