繁体   English   中英

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

[英]How to rightly place a return Value in the recursive python function

我正在遍历二叉树中节点的子节点并检查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)

status始终为True ,即使执行else语句也是如此。

为了正确执行递归,让我们看一下基本情况:

  • 如果当前节点已解锁,则返回False
  • 如果left存在并且已解锁,则返回False
  • 如果right存在并且已解锁,则返回False
  • 返回真

在检查leftright应该完成递归:

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())

由于andor短路运算符,因此仅检查需要检查的树。 请注意,与您的原始代码不同,我们使用子代调用中的返回值。

根据评论,您可以使用内置的all泛化此方法。 尽管对于二叉树不是特别有用,但是这种方法可以很好地推广到任意n元树:

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

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

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

您试图将flag当作某个全局变量来处理,但是它对于每个被调用的lock()实例而言都是局部的。 请注意,这是一件好事-如果您有多个对象,它们肯定不应该共享相同的flag 在某些情况下,将flag更改为类的属性仍然会出现问题。

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

flag = self.lock(node_object.left)而不是仅调用self.lock(node_object.left) 我建议将flag重命名为result ,因为这的确是这样:保存结果的变量。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM