【问题标题】:Recursive function with yield doesn't return anything带有 yield 的递归函数不返回任何内容
【发布时间】:2012-08-23 08:09:46
【问题描述】:

我正在尝试创建一个用于排列目的的生成器。我知道在 Python 中还有其他方法可以做到这一点,但这是为了别的。不幸的是,我无法产生这些值。你能帮忙吗?

def perm(s,p=0,ii=0):
    l=len(s)
    s=list(s)
    if(l==1):       
        print ''.join(s)
    elif((l-p)==2):
        yield ''.join(s)
        yield ''.join([''.join(s[:-2]),s[-1],s[-2]])
    else:
        for i in range(p,l):
            tmp=s[p]
            s[p]=s[i]
            s[i]=tmp        
            perm(s,p+1,ii)

【问题讨论】:

  • 您可以使用''.join(s[:-2] + [s[-1], s[-2]]) 或不太明显的''.join(s[:-2] + s[:-3:-1]) 代替''.join([''.join(s[:-2]),s[-1],s[-2]])(从末尾向后切,但不包括末尾的第三个字符)。跨度>

标签: python recursion generator yield


【解决方案1】:

你的行 perm(s,p+1,ii) 真的什么都没做:就像打字一样

>>> perm("fred")
<generator object perm at 0xb72b9cd4>

如果你从那个调用中让步,即

        for subperm in perm(s, p+1, ii):
            yield subperm

然后你会得到

>>> list(perm("abc"))
['abc', 'acb', 'bac', 'bca', 'cab', 'cba']
>>> list(perm("abcd"))
['abcd', 'abdc', 'acbd', 'acdb', 'adbc', 'adcb', 'bacd', 'badc', 'bcad', 'bcda', 'bdac', 'bdca', 'cabd', 'cadb', 'cbad', 'cbda', 'cdab', 'cdba', 'dabc', 'dacb', 'dbac', 'dbca', 'dcab', 'dcba']

>>> len(_)
24
>>> len(set(perm("abcd")))
24

看起来不错。除此之外,我还没有测试过代码。

顺便说一句,你可以把s[i]s[p]换成s[i], s[p] = s[p], s[i];不需要tmp 变量。

PS:现在你不处理一个字符的情况。

【讨论】:

  • print 语句判断,OP 正在使用 Python 2,但仍在发布的候选 Python 3.3 的yield from perm(s, p+1, ii) 也会这样做。 :)
【解决方案2】:

在生成器中,任何时候你想返回一个值,你都必须给yield。就像你有一个递归阶乘函数,看起来像这样:

>>> def fact(n, result=1):
    if n==0: return result
    fact(n-1, result*n)

然后你想知道为什么它没有返回任何东西:

>>> fact(5)
>>>

原因是函数被递归调用,但是值丢失了。你会想做:

>>> def fact(n, result=1):
    if n==0: return result
    return fact(n-1, result*n)

>>> fact(5)
120

类似地,在你的算法的递归部分你做:

    for i in range(p,l):
        tmp=s[p]
        s[p]=s[i]
        s[i]=tmp        
        perm(s,p+1,ii)

这不是yield 任何东西,所以不会返回来自perm(s,p+1,ii) 调用的任何值(编辑:实际上,它们甚至都不会被计算)。您需要遍历递归调用的结果并依次返回每个结果:

    for i in range(p,l):
        tmp=s[p]
        s[p]=s[i]
        s[i]=tmp        
        for result in perm(s,p+1,ii):
            yield result

【讨论】:

  • 值得指出的是,事实上,perm(s, p+1, ii) 中的任何值都不会被计算。
  • 确实,我在最初的回答中有这个,但决定不包括它......将编辑
猜你喜欢
  • 2021-07-23
  • 2014-04-18
  • 2016-02-15
  • 2012-11-27
  • 2015-04-30
  • 2018-08-27
  • 1970-01-01
  • 1970-01-01
  • 2015-06-07
相关资源
最近更新 更多