2012-04-20 100 views
2
def function(s): 
if len(s) == 1: 
    print s[0], 
else: 
    function(s[1:]) 
    print s[0], 

function("1234")結束了打印4 3 2 1這個輸出爲什麼會發生?

爲什麼會出現這種情況?在功能上,顯然第一個條件沒有得到滿足。在其他情況下,s[1:]被放入s中,但它的長度不是1.我只是看不到s[0]以外的任何東西會被打印到屏幕上。這個功能沒有任何東西看起來像打印s[1:],更不用說相反了。我很困惑。

回答

1

這是一個遞歸的例子,你用原來輸入的短而短的子串重複調用函數本身,直到它是一個長度爲1的字符串(在原始輸入中的最後一個),在這種情況下它開始打印它,然後「展開」並反向打印剩餘的字符串。

在這個annoted代碼看看:

def function(s): 
    if len(s) == 1: 
     print 'single:', s[0], # (A) this is where your first output is generated for a single character 
    else: 
     print 'calling function again with ',s[1:] 
     function(s[1:]) # (B) you call function again, i.e., your recursive call 
     print ' unwind->', s[0], # (C) the "unwinding" step, i.e, finish the rest 
           # of the function when you return from the recursive call 

你得到的輸出是:

calling function again with 234 
calling function again with 34 
calling function again with 4 
single: 4 unwind-> 3 unwind-> 2 unwind-> 1 

你叫你通過對else條款和線(下降函數的第一次B)你再次調用函數,但是這次用「234」。現在函數再次啓動,但是以「234」開始,然後再次進入else,現在再次調用函數,但現在再次運行「34」,函數再次運行,現在再次調用else,並調用函數「4」這一次,因爲它的長度爲1,你打印它(A行)。

現在,您從此函數返回(展開過程) - 並從您進行遞歸調用之前的位置恢復,並通過打印當前剩餘字符的第一個字符來反向打印剩餘的字符串(C行)。

第一次遇到它時很難掌握遞歸 - 這很正常。在某個時候,它會點擊並變得清晰。您可能想要閱讀一般概念並找出一些清晰的註釋示例(大多數CS /編程書籍會有一些)。

下面是一個簡短的YouTube視頻,說明遞歸Python中一個簡單的例子,希望它有助於:http://www.youtube.com/watch?v=72hal4Cp_2I

+0

我還是輸了。我也不太瞭解遞歸。是不是,如果你再次調用該函數,它會繼續調用它,因爲s [1:]的長度永遠不是1,所以不會打印任何內容? – VPNTIME 2012-04-20 03:11:37

+0

@Omerta你缺少的是每次調用'function'時's'都是一個*不同's' *。一旦你有了,'len(s [1:])'最終會變爲1. – lvc 2012-04-20 03:17:13

+0

謝謝Levon。我現在真的明白了。 – VPNTIME 2012-04-20 04:39:25

9
>>> def function(s): 
...  print 's is currently %r' % s 
...  if len(s) == 1: 
...   print s[0], 
...  else: 
...   function(s[1:]) 
...   print s[0], 
... 
>>> function("1234") 
s is currently '1234' 
s is currently '234' 
s is currently '34' 
s is currently '4' 
4 3 2 1 

這是一個遞歸函數,而且它打印年代以前再次調用自身[0]所以它打印出的項目是相反的。

下面是一個可能更有幫助的例子。

>>> def function(s): 
...  print 's is currently %r' % s 
...  if len(s) > 1: 
...   print 'calling function again with %r as s' % s[1:] 
...   function(s[1:]) 
...  print s[0], 
... 
>>> function('1234') 
s is currently '1234' 
calling function again with '234' as s 
s is currently '234' 
calling function again with '34' as s 
s is currently '34' 
calling function again with '4' as s 
s is currently '4' 
4 3 2 1 
1

嘗試修改函數如下:

def function(s): 
    print 'Called with {}'.format(s) 
    if len(s) == 1: 
     print s[0] 
    else: 
     function(s[1:]) 
     print s[0] 

並運行它。您會看到每次點擊function(s[1:])時,您都暫停了「運行」function(),並在現在暫時掛起的一箇中啓動了新運行function()。對function()的新呼叫使用字符串的縮短版本。最終,它只有一個字符纔會被調用,並且達到了第一個條件。

從內部調用函數稱爲遞歸

0

讓我們看看工作中的遞歸。

  • 首先調用與S功能= 「1234」
  • LEN(S)= 4,所以你拿別人
  • 你調用函數遞歸s[1:]或 「234」
    • 現在,你是在用S = 「234」
    • LEN(S)= 3的功能,所以你拿別人
    • 您與s[1:]或 「34」遞歸調用函數現在
      • ,你是在用S = 「34」
      • LEN(S)= 2的功能,所以你拿別人
      • 你叫遞歸地s[1:]功能或 「34」 現在
        • ,你在與S4"
        • LEN(S)= 1,因此功能你做的,如果和和打印s[0]即4
        • 將返回
      • 第一部分
      • 返回到先前的呼叫(S = 「34」)打印s[0],即3
      • 將返回
    • 返回到先前的呼叫(S = 「234」)打印s[0],即2
    • 你返回
  • CReturning以前調用(S = 「1234」)打印s[0],即1
  • 將返回