2012-09-04 185 views
1

我試圖在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 
+2

因爲你沒有在'else'子句中返回任何東西 – JBernardo

回答

7

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

在Python中,你必須實際使用return語句從函數返回的東西,否則返回None

+0

謝謝,它的工作原理!我對這個邏輯有點困惑:爲什麼不能在'else'之前返回一個值,而不是依賴程序第一次運行的地方? (例如在else語句之後)。 – idlackage

+1

發生什麼是第一個函數調用進行第二次函數調用。 * second *調用返回self,但第一個調用需要返回第二個調用的結果,而不是將結果放在地板上。 – Gabe

+0

這不是Python特定的。 –

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> 
1

返回selfifTrue側的工作就好了。但是,else側的遞歸調用不會返回任何內容。改爲使用return self.owner.getTopParent()

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」調用獲取從self.owner.getTopParent()返回的值None。然後退出該函數的結尾,返回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與致電self.owner.getTopParent()None無關。

[3]除非您直接在交互式解釋器中鍵入該值,否則Python將爲您輸出返回值,以便您可以看到它是什麼。它也祕密地將它保存在變量_中,所以如果你認爲在看到它之後確實需要它,那麼你可以得到它的結果。但從原則上和其他任何環境來看,如果你對任何你所稱的東西的回報價值沒有做任何事情,那麼你就失去了價值。