Python:使用递归算法作为生成器
最近我写了一个函数来生成具有非平凡约束的特定序列。 问题出现在自然递归解决方案中。 现在碰巧,即使是相对较小的输入,序列也有数千个,因此我宁愿将我的算法用作生成器,而不是用它来填充所有序列的列表。
这是一个例子。 假设我们想用递归函数计算一个字符串的所有排列。 下面的朴素算法需要一个额外的参数“存储”,并且每当它找到一个时就附加一个置换:
def getPermutations(string, storage, prefix=""):
   if len(string) == 1:
      storage.append(prefix + string)   # <-----
   else:
      for i in range(len(string)):
         getPermutations(string[:i]+string[i+1:], storage, prefix+string[i])
storage = []
getPermutations("abcd", storage)
for permutation in storage: print permutation
(请不要关心低效率,这只是一个例子。)
现在我想把我的函数变成一个生成器,即产生一个排列而不是将它附加到存储列表中:
def getPermutations(string, prefix=""):
   if len(string) == 1:
      yield prefix + string             # <-----
   else:
      for i in range(len(string)):
         getPermutations(string[:i]+string[i+1:], prefix+string[i])
for permutation in getPermutations("abcd"):
   print permutation
此代码不起作用(该函数的行为类似于空的生成器)。
我错过了什么吗? 有没有办法将上面的递归算法变成一个生成器而不用迭代器替换它?
def getPermutations(string, prefix=""):
    if len(string) == 1:
        yield prefix + string
    else:
        for i in xrange(len(string)):
            for perm in getPermutations(string[:i] + string[i+1:], prefix+string[i]):
                yield perm
或者没有累加器:
def getPermutations(string):
    if len(string) == 1:
        yield string
    else:
        for i in xrange(len(string)):
            for perm in getPermutations(string[:i] + string[i+1:]):
                yield string[i] + perm
  这避免了len(string)深度递归,并且通常是处理generator-inside-generators中的一个好方法: 
from types import GeneratorType
def flatten(*stack):
    stack = list(stack)
    while stack:
        try: x = stack[0].next()
        except StopIteration:
            stack.pop(0)
            continue
        if isinstance(x, GeneratorType): stack.insert(0, x)
        else: yield x
def _getPermutations(string, prefix=""):
    if len(string) == 1: yield prefix + string
    else: yield (_getPermutations(string[:i]+string[i+1:], prefix+string[i])
            for i in range(len(string)))
def getPermutations(string): return flatten(_getPermutations(string))
for permutation in getPermutations("abcd"): print permutation
  flatten使我们能够通过简单地继续在另一个生成进度yield荷兰国际集团它,而不是通过它迭代和yield手动荷兰国际集团的每个项目。 
  Python 3.3将从语法中增加yield from ,从而允许自然委派给子生成器: 
def getPermutations(string, prefix=""):
    if len(string) == 1:
        yield prefix + string
    else:
        for i in range(len(string)):
            yield from getPermutations(string[:i]+string[i+1:], prefix+string[i])
内部调用getPermutations - 它也是一个生成器。
def getPermutations(string, prefix=""):
   if len(string) == 1:
      yield prefix + string            
   else:
      for i in range(len(string)):
         getPermutations(string[:i]+string[i+1:], prefix+string[i])  # <-----
你需要通过for循环来遍历它(参见@MizardX发布,这让我几秒钟就可以完成)!
链接地址: http://www.djcxy.com/p/37283.html