返回结果而不是在函数中打印

时间:2013-12-23 15:05:18

标签: python python-3.x return-value output

我对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

我应该如何更改返回结果的代码而不打印它?

谢谢!

4 个答案:

答案 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
    )