简体   繁体   English

使用生成器生成排列

[英]Generating permutations using generators

I was writing a program to generate all the permutations of a string: 我正在编写一个程序来生成字符串的所有排列:

def print_permutations_wrapper(str):
    strList = str.split()
    print_permutations(strList, 0, len(strList))


def print_permutations(strList: list, start: int, end: int):
    if start >= end - 1:
        print(strList)
        return

    print_permutations(strList, start+1, end)
    for i in range(start+1, end):
        strList[start], strList[i] = strList[i], strList[start]
        print_permutations(strList, start+1, end)
        strList[i], strList[start] = strList[start], strList[i]


def main():
    str = 'a b c'
    print_permutations_wrapper(str)


if __name__ == "__main__":
    main()

Its working correctly, but rather than printing it, I wanted to return it lazily using yield : 它可以正常工作,但我不想使用yield来将其延迟返回,而不是打印它:

def print_permutations_wrapper(str):
    strList = str.split()
    yield from print_permutations(strList, 0, len(strList))


def print_permutations(strList: list, start: int, end: int):
    if start >= end - 1:
        yield strList
        return

    yield from print_permutations(strList, start+1, end)
    for i in range(start+1, end):
        strList[start], strList[i] = strList[i], strList[start]
        yield from print_permutations(strList, start+1, end)
        strList[i], strList[start] = strList[start], strList[i]


def main():
    str = 'a b c'
    x = print_permutations_wrapper(str)
    print(list(x))

if __name__ == "__main__":
    main()

The output that I get is: 我得到的输出是:

[['a', 'b', 'c'], ['a', 'b', 'c'], ['a', 'b', 'c'], ['a', 'b', 'c'], ['a', 'b', 'c'], ['a', 'b', 'c']]

rather than all the permutations. 而不是所有排列。
How to correct this? 如何纠正呢?

I am using Python 3.7. 我正在使用Python 3.7。

Taking your second program, but add a print(strList) will show that the generator function yielded what you expected, but the final output is clearly not what you expected. 使用第二个程序,但是添加一个print(strList)将显示generator函数产生了您期望的结果,但是最终输出显然不是您期望的结果。 This is due to the fact that the program as structured takes a list, but does all the operation to this same copy (assumed to limit memory usage). 这是由于这样的事实:结构化的程序带有一个列表,但是对同一副本执行所有操作(假定限制了内存的使用)。 You can also verify this by 您也可以通过以下方式进行验证

>>> strList = ['a', 'b', 'c'] 
>>> items = list(print_permutations(strList, 0, 3))
>>> items[0] is items[1]
True
>>> items[0] is strList
True

Clearly every single item inside the items are of the same original strList that got passed in. Given the simplicity of the problem, this may be avoided by yielding a shallow copy of the list instead. 显然, items中的每个items都与传入的原始strList相同。鉴于问题的简单性,可以通过产生列表的浅表副本来避免此问题。 Thus the relevant yield part of the function will become 因此,函数的相关yield部分将变为

def print_permutations(strList: list, start: int, end: int):
    if start >= end - 1:
        yield list(strList)
        return

Now running it should produce: 现在运行它应该产生:

>>> strList = ['a', 'b', 'c'] 
>>> items = list(print_permutations(strList, 0, 3))
>>> items[0] is items[1]
False

Also, as an aside, permutation is in fact a part of the standard library, available via itertools.permutation . 另外,排列实际上是标准库的一部分,可通过itertools.permutation

Related: "Least Astonishment" and the Mutable Default Argument 相关: “最小惊讶”和可变的默认参数

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM