如何在递归python函数中正确放置返回值

如何在递归python函数中正确放置返回值,python,python-3.x,binary-tree,Python,Python 3.x,Binary Tree,我正在遍历二叉树中节点的子节点,并检查locked属性。如果任何子锁状态为False,则返回False,否则返回True。我似乎找不到在代码中放置return语句的正确方法。请注意,lock函数的输入是一个节点对象 class BinaryTree(): def __init__(self, value, lock=False): self.locked = lock self.value = value self.left = None

我正在遍历二叉树中节点的子节点,并检查
locked
属性。如果任何子锁状态为
False
,则返回
False
,否则返回
True
。我似乎找不到在代码中放置
return
语句的正确方法。请注意,
lock
函数的输入是一个节点对象

class BinaryTree():
    def __init__(self, value, lock=False):
        self.locked = lock
        self.value = value
        self.left = None
        self.right = None

    def lock(self, node_object):
        """lock a node if the descendants are locked using post-order traversing"""
        flag = True
        if node_object.left:
            if node_object.left.locked == True:
                print(
                    f'>>> Left child: {node_object.left.value}. Locked?: {node_object.left.locked} <<<')
                self.lock(node_object.left)
            else:
                flag = False
                print(
                    f'>>> Children Node: {node_object.left.value}\tstate: {node_object.left.locked}. Lock failed <<<')
        if node_object.right:
            if node_object.right.locked == True:
                print(
                    f'>>> Right child: {node_object.right.value}. Locked?: {node_object.right.locked} <<<')
                self.lock(node_object.right)
            else:
                flag = False
                print(
                    f'>>> Children Node: {node_object.right.value}\tstate: {node_object.right.locked}. Lock failed <<<')
        return flag

# test the functions
if __name__ == "__main__":
    BT = BinaryTree(None)
    count = 0
    lock_state = False
    nodes = [34, 2, 1, 6, 8, 9, 56, 99, 150, 45, 3]
    for item in nodes:
        BT.add_node(item, lock_state)  # test add_node
    node = BT.find_node(56)  # test find_node function
    if node is not None:
        status = BT.lock(node)
        print(status)
class BinaryTree():
定义初始化(self,value,lock=False):
自锁
自我价值=价值
self.left=无
self.right=无
def锁(自身、节点\对象):
“”“如果使用后序遍历锁定子体,则锁定节点”“”
flag=True
如果节点_object.left:
如果节点_object.left.locked==True:
印刷品(

左子节点:{node_object.Left.value}.Locked?:{node_object.Left.Locked}子节点:{node_object.Left.value}\t状态:{node_object.Left.Locked}.Lock失败右子节点:{node_object.Right.value}.Locked?:{node_object.Right.Locked}子节点:{node_object.Right.value}\t状态:{node_object Right.Locked}.Lock失败要正确执行递归,让我们看看基本情况:

  • 如果当前节点已解锁,则返回False
  • 如果
    left
    存在且已解锁,则返回False
  • 如果
    right
    存在且已解锁,则返回False
  • 返回真值
左侧
右侧
的检查应递归进行:

def is_locked(self):
     return self.locked and (not self.left or self.left.is_locked()) and (not self.right or self.right.is_locked())
由于
都是短路运算符,因此只会检查需要检查的树。请注意,与原始代码不同,我们使用子级调用的返回值

根据注释,您可以使用内置的
all
来概括此方法。虽然此方法对二叉树不是特别有用,但它可以很好地概括任意n元树:

def is_locked(self):
    return self.locked and all(node.is_locked() for node in (self.left, self.right) if node)

n元树可能具有可变序列属性
self.children
,而不是
(self.left,self.right)

要正确递归,让我们看看基本情况:

  • 如果当前节点已解锁,则返回False
  • 如果
    left
    存在且已解锁,则返回False
  • 如果
    right
    存在且已解锁,则返回False
  • 返回真值
左侧
右侧
的检查应递归进行:

def is_locked(self):
     return self.locked and (not self.left or self.left.is_locked()) and (not self.right or self.right.is_locked())
由于
都是短路运算符,因此只会检查需要检查的树。请注意,与原始代码不同,我们使用子级调用的返回值

根据注释,您可以使用内置的
all
来概括此方法。虽然此方法对二叉树不是特别有用,但它可以很好地概括任意n元树:

def is_locked(self):
    return self.locked and all(node.is_locked() for node in (self.left, self.right) if node)

n元树可能有一个可变序列属性
self.children
,而不是
(self.left,self.right)

对递归函数的每次新调用都会将该函数的一个新实例放在一个堆栈上,并带有它自己的局部变量副本

您试图操纵
标志,就好像它是某个全局变量一样,但它是
lock()的每个被调用实例的局部变量
。请注意,这是一件好事-如果您有多个对象,它们肯定不应该共享同一个
标志
。在某些情况下,将
标志
更改为类的属性仍然会有问题

您在正确的轨道上,尝试返回一个结果,但是当您使用
self.lock()
进行递归调用时,这些调用将返回该节的结果,因此您应该捕获返回值并处理它,正如其他人所建议的那样

i、 e.
flag=self.lock(node\u object.left)
而不是只调用
self.lock(node\u object.left)
。我建议将
flag
重命名为
result
,因为它实际上就是一个保存结果的变量


作为一项改进,您可以将所有
标志=
语句更改为
返回
语句,而不是将结果分配给
标志
,并在最后返回它-因为您除了返回结果之外不在任何地方使用
标志
语句。没有禁止多个返回的规则语句,尽管某些纯粹主义者可能出于特定原因不喜欢它。

对递归函数的每次新调用都会将该函数的新实例放在堆栈上,并带有其自身的局部变量副本

您试图操纵
标志,就好像它是某个全局变量一样,但它是
lock()的每个被调用实例的局部变量
。请注意,这是一件好事-如果您有多个对象,它们肯定不应该共享同一个
标志
。在某些情况下,将
标志
更改为类的属性仍然会有问题

您在正确的轨道上,尝试返回一个结果,但是当您使用
self.lock()
进行递归调用时,这些调用将返回该节的结果,因此您应该捕获返回值并处理它,正如其他人所建议的那样

i、 e.
flag=self.lock(node\u object.left)
而不是只调用
self.lock(node\u object.left)
。我建议将
flag
重命名为
result
,因为它实际上就是一个保存结果的变量

作为一项改进,您可以将所有
标志=
语句更改为
返回
语句,而不是将结果分配给
标志
,并在最后返回它-因为您除了返回结果之外不在任何地方使用
标志
语句。没有禁止多个返回的规则s