为什么'返回自我'返回无?

时间:2012-09-04 22:42:45

标签: python return-value

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

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 个答案:

答案 0 :(得分:7)

您需要返回 self.owner.getTopParent()

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

答案 1 :(得分: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>

答案 2 :(得分: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,因此返回给“check 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

现在,每个“check childN”调用都会通过调用self.owner.getTopParent() 接收一个值并将其返回到下一个最外面的调用者。

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

self.owner.getTopParent()

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

您正在调用的函数恰好与您所使用的函数具有相同的名称这一事实无关紧要;递归调用与每个单向的非递归调用完全相同。我总是对许多人的混乱递归感到惊讶,但这可能只是因为我不记得再学习它是什么感觉了。 :)


[1]如果你仔细想想,return 以这种方式工作。你怎么能编写一个调用其他函数的函数,如果它们返回时返回值一直跳到最外面的调用(并且如果你在交互式解释器中运行则显示为输出)?

[2]此None与从None的通话中接收self.owner.getTopParent()无关。

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

答案 3 :(得分:1)

返回selfTrue的{​​{1}}方面工作得很好。但是,if方的递归调用不会返回任何内容。请改用else