Python 具有yield的递归函数不返回任何内容

Python 具有yield的递归函数不返回任何内容,python,recursion,generator,yield,Python,Recursion,Generator,Yield,我正在尝试创建一个用于排列的生成器。我知道在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]

我正在尝试创建一个用于排列的生成器。我知道在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)
你的线烫发,p+1,ii什么都不做,真的:就像打字一样

>>> perm("fred")
<generator object perm at 0xb72b9cd4>
然后你会得到

>>> 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[p],s[i]交换s[i]和s[p];不需要tmp变量

PS:现在你不需要处理一个字符的大小写。

你的行烫发,p+1,ii什么都不做,真的:就像打字一样

>>> perm("fred")
<generator object perm at 0xb72b9cd4>
然后你会得到

>>> 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[p],s[i]交换s[i]和s[p];不需要tmp变量


PS:现在你不需要处理一个字符的大小写。

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

>>> 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)
但是,这不会产生任何结果,因此perms,p+1,ii调用中的任何值都不会返回EDIT:实际上,它们甚至都不会被计算。您需要迭代递归调用的结果,并依次返回每个结果:

    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

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

>>> 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)
但是,这不会产生任何结果,因此perms,p+1,ii调用中的任何值都不会返回EDIT:实际上,它们甚至都不会被计算。您需要迭代递归调用的结果,并依次返回每个结果:

    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

代替.join[.join[:-2],s[-1],s[-2]],您可以执行.join[-2]+[s[-1],s[-2]]或稍不明显的.join[:-2]+s[:-3:-1],它从结尾向后切片,但不包括从结尾开始的第三个字符。您可以执行.join[.join[.joins[-2]+[s[-1],s[-2]]从print语句判断,joins[:-2]+s[:-3:-1]从结尾向后切片,但不包括结尾处的第三个字符。OP使用的是Python 2,但在发行版候选Python 3.3中,perms的收益率p+1,ii也会这样做从print语句来看,OP使用的是python2,但在发布候选版python3.3中,perms的收益率p+1,ii也可以做到这一点值得一提的是,事实上,perms,p+1,ii中的任何值都不会被计算出来。事实上,我在最初的答案中有这个,但决定不包括它。。。will editWorth指出,事实上,perms,p+1,ii中的任何值都不会被计算出来。事实上,我在最初的答案中有这个,但决定不包括它。。。将编辑