2013-12-23 72 views
-2

我有一個關於Python的問題。返回結果而不是在函數中打印

我有一個遞歸函數:

def func(num, k): 

    if k == 0: 
     print(num, end = '') 
     return 

    for item in num: 
     if item == '1': 
      func('123', k-1) 
     elif item == '2': 
      func('321', k-1) 
     elif item == '3': 
      func('1', k-1) 

運行這段代碼func('2', 3)打印: 12313211231233211

然而,實際上,我不希望函數打印結果。我想讓它返回。所以,如果我運行該程序爲a = func('2', 3)那麼程序不會打印任何內容。現在我可以使用a以外的功能,例如打印print(a),其產生12313211231233211

我應該如何更改它返回結果並不打印它的代碼?

謝謝!

回答

2
def func(num, k, result=None): 
    if result is None: 
     result = [] 
    if k == 0: 
     result.append(num) 
    else: 
     for item in num: 
      if item == '1': 
       func('123', k-1, result) 
      elif item == '2': 
       func('321', k-1, result) 
      elif item == '3': 
       func('1', k-1, result) 
    return "".join(result) 

我加入了result參數,但只是抱着解決方案,您不需要提供任何列表中運行此版本。只要運行它就像你貼:

print func('2', 3) 
+0

現在試試我剛編輯 –

+1

我試過這個,'func(「2」,3)''''123'。我不認爲這是正確的。 – Kevin

+0

@凱文是的,我現在得到了同樣的答案'123'。但是,是的,這是不正確的。 – user3129888

1

在Python 3.3:

def iter_func(num, k): 
    if k == 0: 
     yield num 
    else: 
     for item in num: 
      if item == '1': 
       yield from iter_func('123', k-1) 
      elif item == '2': 
       yield from iter_func('321', k-1) 
      else: 
       yield from iter_func('1', k-1) 

def func(num, k): 
    return ''.join(iter_func(num, k)) 

在較早的Python版本是沒有yield from,但是可以達到同樣具有:

for x in whatever: 
    yield x 

通過方式,你也可以通過重組簡化一些,特別是如果你不使用3.3,所以在每種情況下都需要額外的代碼:

subvalues = {'1' : '123', '2': '321'} 

... 

for item in num: 
    yield from iter_func(subvalues.get(item, '1'), k-1) 

多說了同樣的事情的另一種方法:

import itertools 

subvalues = {'1' : '123', '2': '321'} 
def iter_func(num, k): 
    if k == 0: 
     return (num,) 
    return itertools.chain.from_iterable(
     iter_func(subvalues.get(item, '1'), k-1) 
     for item in num 
    ) 
+0

謝謝!由於我是Python的初學者,我需要搜索更多關於「yield」的信息。我沒想到會更改我的代碼。不過謝謝。 – user3129888

+0

@ user3129888:好吧,還有其他的方法可以做到這一點,所以你不用*查找'yield',但我建議你做:-)例如,你可以在這個地方傳遞一個列表,並附加一個值顯示在您當前打印的地方。儘管如此,您仍然需要將它們連接在一起,並且無論如何,yield都是用來產生一系列值的自然事物(我敢說「Pythonic」)。 –

+0

好的,謝謝! :-) – user3129888

3

這裏有一個辦法做到這一點,你不必改變你的函數的代碼。相反,我們將創建一個函數裝飾器,它靜靜捕捉所有打印的輸出,並將其保存以備後用。

import sys 
from io import StringIO 

def returnStdout(fn): 
    silent_stdout = StringIO() 
    def silentFn(*args, depth=0, **kargs): 
     nonlocal silent_stdout 

     #only replace stdout if it hasn't been replaced already. 
     #this may be important if we decorate a recursive function. 
     if sys.stdout != silent_stdout: 
      old_stdout = sys.stdout 
      sys.stdout = silent_stdout 
      fn(*args, **kargs) 
      sys.stdout = old_stdout 
      result = silent_stdout.getvalue() 

      #clear silent_stdout so the next call to the decorated function doesn't contain the values of previous calls 
      silent_stdout = StringIO() 

      return result 
     else: 
      fn(*args, **kargs) 
    return silentFn 

@returnStdout 
def func(num, k): 

    if k == 0: 
     print(num, end = '') 
     return 

    for item in num: 
     if item == '1': 
      func('123', k-1) 
     elif item == '2': 
      func('321', k-1) 
     elif item == '3': 
      func('1', k-1) 


result = func("2", 3) 
print("got result. Result is:") 
print(result) 

結果:

got result. Result is: 
12313211231233211 
2

這裏是另一種方式來做到這一點。

def func(num, k, m={'1':'123','2':'321','3':'1'}): 
    def recurs(s, c, r=''): 
     return s if c == 0 else ''.join([recurs(m.get(i,''), c-1) for i in s]) 
    return recurs(num, k) 

>>> func('2', 3) 
'12313211231233211'