有人能解释一下这个Python排列代码吗?

3
我看到这里发布了一些排列的代码,但我实际上没有找到一个好的逐步介绍正在发生什么的教程。如果有人能够解释一下这个代码在每个步骤中实际上是发生了什么,我会非常感激。我似乎无法理解它。我要看的代码是Python中来自http://snippets.dzone.com/posts/show/753 的代码。
def all_perms(str):
    if len(str) <=1:
        yield str
    else:
        for perm in all_perms(str[1:]):
            for i in range(len(perm)+1):
                yield perm[:i] + str[0:1] + perm[i:]


for p in all_perms(['a','b','c']):
    print p
3个回答

2
def all_perms(str):
    # If there is only one item, there can be only one permutation
    # yield the single item
    if len(str) <=1:
        yield str
    else:
        # loop over the permutations returned by a recursive call to all_perms
        # note it is passing a subset of the list passed in.
        for perm in all_perms(str[1:]):
            # for each returned sub-permutation insert the item that
            # wasn't passed into each possible position.
            for i in range(len(perm)+1):
                yield perm[:i] + str[0:1] + perm[i:]


for p in all_perms(['a','b','c']):
    print p

所以你传入了['a','b','c']

它调用all_perms(['b', 'c']),并调用all_perms(['c']),这将产生'c'。

yield语句意味着all_perms()是一个生成器,它调用自身意味着它正在使用递归

我建议使用itertools.permutations而不是那个片段。


谢谢,这非常有帮助。我知道itertools.permutations,但我真的想更好地理解我发帖的代码中正在发生的事情。再次感谢! - bb89

1
你看到的是一个迭代器生成器。它是一个返回可循环遍历的对象的函数。
for循环执行期间,all_perms被执行直到它遇到一个yield语句。yield的值作为变量p传递给循环。然后all_perms的执行继续在yield语句之后的位置继续上次退出方法的位置。

1

首先,参数str的名称选择不当。这可能是因为它适用于Python中的所有种类的序列类型,但应该使用seq或其他名称以清晰地表达意图。

  1. 如果列表长度小于等于1(空或一个元素),则返回列表(对于此情况只有一种解决方案)。

  2. 对于所有其他情况:

    a)创建str [1:]的所有排列(即仅包含头元素的列表)。

    b)将头元素插入到a)中创建的每个排列中的每个位置,并返回结果

yield的工作方式有点像return;主要区别在于当前值被返回,并且当再次调用函数时,它会继续执行yield后的指令。

这样,就可以轻松组装结果。

例如:

'a' 返回 'a'(平凡)。 'ab' 首先去掉头部('a'),然后创建所有的排列组合 b(只有一个:'b'本身)。现在将头部插入到每个位置,因此我们最终得到 'ab'(头部+列表)和 'ba'(列表+头部)。

等等。


谢谢!这正是我一直在寻找的。yield和递归的结合一开始让我难以理解,但现在我明白了。我知道你说的str变量是什么意思。如果是我写的话,我也不会给它起这个名字,但我只是从我在原帖中提到的网站上抓取了它。再次感谢! - bb89
当你给变量命名合适的名称时,一些代码会变得非常简单,这是令人惊讶的。这就是我提到它的原因。 - Aaron Digulla

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接