我对您的代码做了一些细微的修改:
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”调用获取None
从self.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
无关。None
self.owner.getTopParent()
[3] 除非您直接在交互式解释器中输入,否则 Python 会为您打印返回值,以便您查看它是什么。它还秘密地将它保存在变量_
中,所以如果你在看到它之后决定你确实需要它,你就可以得到它是什么。但原则上,在任何其他情况下,如果你不对你调用的东西的返回值做任何事情,那么你就会失去价值。