1

我正在尝试获取链的顶部节点getTopParent()。当我打印出来时self.name,它确实打印出父实例的名称;但是,当我返回时self,它返回无。为什么是这样?

class A:
    def __init__( self, name ):
        self.name = name
        self.owner = None
    def setChild( self, l ):
        l.owner = self
    def getTopParent( self ):
        if( self.owner == None ): # None == top parent
            print( "Got top: %s" % self.name )
            return self
        else:
            print( "checking %s" % self.name )
            self.owner.getTopParent()

a = A( "parent" )
b = A( "child1" )
c = A( "child2" )
d = A( "child3" )
a.setChild( b )
b.setChild( c )
c.setChild( d )

print( d.getTopParent() )
>>> checking child3
    checking child2
    checking child1
    Got top: parent
    None
4

4 回答 4

7

你需要回来 self.owner.getTopParent()

在 Python 中,您必须实际使用return语句从函数中返回某些内容,否则None返回。

于 2012-09-04T22:43:52.763 回答
3

用于return_

else:
    print( "checking %s" % self.name )
    return self.owner.getTopParent()

None默认返回值一样,然后它会输出:

checking child3
checking child2
checking child1
Got top: parent
<__main__.A instance at 0xb77a628c>
于 2012-09-04T22:44:52.787 回答
2

我对您的代码做了一些细微的修改:

class A:
    def __init__( self, name ):
        self.name = name
        self.owner = None
    def setChild( self, l ):
        l.owner = self
    def getTopParent( self , depth=0):
        if( self.owner == None ): # None == top parent
            print( '  ' * depth + "Got top: %s" % self.name )
            print( '  ' * depth + "Returning: %s" % self)
            return self
        else:
            print( '  ' * depth + "checking %s" % self.name )
            tmp = self.owner.getTopParent(depth=depth + 1)
            print( '  ' * depth + "returned from call while checking %s" % self.name)
            print( '  ' * depth + "returned value was: %s" % tmp)


a = A( "parent" )
b = A( "child1" )
c = A( "child2" )
d = A( "child3" )
a.setChild( b )
b.setChild( c )
c.setChild( d )


d_top_parent = d.getTopParent()
print('----------------')
print d_top_parent

现在您可以在调用 时看到发生了什么d.getTopParent()。这是输出:

checking child3
  checking child2
    checking child1
      Got top: parent
      Returning: <__main__.A instance at 0x0000000002DE8DC8>
    returned from call while checking child1
    returned value was: <__main__.A instance at 0x0000000002DE8DC8>
  returned from call while checking child2
  returned value was: None
returned from call while checking child3
returned value was: None
----------------
None

在中间,您可以看到它找到了顶级父级并将其返回。但return返回到从 [1] 调用此函数的地方。所以这只返回到“检查child1”调用。

回到“检查 child1”调用中,它被称为self.owner.getTopParent(),它返回了最高父级。在您的原始版本中,此后没有更多代码,因此执行“从函数的末尾掉线”。在我的版本中,它将返回的值存储self.owner.getTopParent()到一个变量tmp中并打印出来,这样我们就可以看到它是什么。但随后它也会退出函数的末尾。

在 Python 中,到达函数的末尾相当于return None,所以这就是返回给“检查 child1”的调用者的内容。因此“检查 child2”调用获取Noneself.owner.getTopParent(). 然后退出函数的末尾,返回None给它的调用者。 [2] 等等。

如果您添加return tmp到我的版本,在else分支中打印后,您会得到以下输出:

checking child3
  checking child2
    checking child1
      Got top: parent
      Returning: <__main__.A instance at 0x0000000002E68DC8>
    returned from call while checking child1
    returned value was: <__main__.A instance at 0x0000000002E68DC8>
  returned from call while checking child2
  returned value was: <__main__.A instance at 0x0000000002E68DC8>
returned from call while checking child3
returned value was: <__main__.A instance at 0x0000000002E68DC8>
----------------
<__main__.A instance at 0x0000000002E68DC8

现在每个“检查 childN”调用都会从调用中接收一个值self.owner.getTopParent() 并将其返回给下一个最外层的调用者。

如果你调用某个东西,并且你希望它的返回值去任何地方,你必须告诉它去哪里。这可以用赋值语句将它存储在某个地方,或者直接将它作为参数传递给另一个调用,或者直接返回它。如果您只是有这样的电话:

self.owner.getTopParent()

然后返回的值无处可去,不能用于任何目的[3]。

您调用的函数恰好与您所在的函数同名这一事实无关紧要。递归调用的工作方式与非递归调用完全相同。我总是对很多人对递归的困惑感到惊讶,但这可能只是因为我不记得学习它是什么感觉了。:)


[1] 如果您考虑一下,return 必须以这种方式工作。如果当它们返回时返回值一直跳到最外层的调用(如果您在交互式解释器中运行,则显示为输出),您如何编写一个调用其他函数的函数?

[2] 这与接收来自 的调用None无关。Noneself.owner.getTopParent()

[3] 除非您直接在交互式解释器中输入,否则 Python 会为您打印返回值,以便您查看它是什么。它还秘密地将它保存在变量_中,所以如果你在看到它之后决定你确实需要它,你就可以得到它是什么。但原则上,在任何其他情况下,如果你不对你调用的东西的返回值做任何事情,那么你就会失去价值。

于 2012-09-04T23:40:41.423 回答
1

返回self工作Trueif. 但是,else侧面的递归调用不会返回任何内容。改为使用return self.owner.getTopParent()

于 2012-09-04T22:45:43.073 回答