我对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
。
我应该如何更改返回结果的代码而不打印它?
谢谢!
答案 0 :(得分: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
答案 1 :(得分: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)
答案 2 :(得分: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'
答案 3 :(得分: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
)