Python初学者被一堆复杂的代码搞糊涂了

时间:2010-04-06 00:34:52

标签: python list-comprehension

我理解代码的要点,它形成了排列;但是,我想知道是否有人能够在退货声明中准确解释发生了什么。

def perm(l):
    sz = len(l)
    print (l)
    if sz <= 1:
        print ('sz <= 1')
        return [l]
    return [p[:i]+[l[0]]+p[i:] for i in range(sz) for p in perm(l[1:])]

5 个答案:

答案 0 :(得分:10)

return正在返回一个列表理解,其项目是通过将l的第一项插入p的每个位置(从第一个到最后一个 - {{1反过来是一个列表列表,通过对p的递归调用获得,该调用排除perm的第一项(从而以所有可能的方式置换所有其他项目)。

如果你不理解递归,那么解释并不是很简单;-)。如果您不理解列表推导,那么 很容易解释 - l在语义上等同于

return

这也表明了这段代码效率低下:它正在递归result = [] for i in range(sz): for p in perm(l[1:]): result.append(p[:i]+[l[0]]+p[i:]) return result perm次,显然没有必要。更好的方法是简单地交换两个sz循环:

for

和相当于这个,更好的代码,是一个列表理解与交换的两个result = [] for p in perm(l[1:]): for i in range(sz): result.append(p[:i]+[l[0]]+p[i:]) return result 子句:

for

答案 1 :(得分:4)

return语句使用列表推导。如果你把它放到实际的循环中,它会更容易理解:

value = []
for i in range(sz):
    # call this function using all but the first item in l
    for p in perm(l[1:]):
        # now place the first item in l between index i-1 and index i in p
        value.append(p[:i] + [l[0]] + p[i:])
return value

答案 2 :(得分:1)

看看这个:

>>> l = [1, 2, 3, 4, 5, 6]
>>> p = l[1:]
>>> p
[2, 3, 4, 5, 6]
>>> i = 3
>>> p[:i]
[2, 3, 4]
>>> p[i:]
[5, 6]
>>> p[:i]+[l[0]]+p[i:]
[2, 3, 4, 1, 5, 6]
>>> 

所以,这就是p代表l[1:]的所有排列(即l减去第一个元素)。接下来,irange(sz),这意味着它从0变为l的长度。这会将p分成两个包含所有可能大小的列表(0和sz,1和sz -1,2和sz - 2等),并插入l的第一个元素 - 那个没有得到置换 - 在这两个列表之间。

答案 3 :(得分:1)

好的,我们开始吧。

开始代码

(减去印刷陈述)

def perm(l):
    sz = len(l)
    if sz <= 1:
        return [l]
    return [p[:i]+[l[0]]+p[i:] for i in range(sz) for p in perm(l[1:])]

修订版1

def perm(s):
    # Base case: an empty list or a list with only one item has only one
    # permutation
    if len(s) <= 1:
        return [s]
    return [p[:i] + [s[0]] + p[i:]
            for i in range(len(s)) for p in perm(s[1:])]
  • l重命名为s
  • 删除sz,而不是直接使用len(s)。我们可能会失去一点点效率,但我们获得了大量的可读性
  • 修复列表理解中的间距

修订版2

def perm(s):
    # Base case: an empty list or a list with only one item has only one
    # permutation
    if len(s) <= 1:
        return [s]

    # A list of permutations
    permutations = []
    for i in range(len(s)):
        # Recursively find all permutations of s[1:]
        for p in perm(s[1:]):
            # Insert s[0] in position i
            permutations.append(p[:i] + [s[0]] + p[i:])
    return permutations
  • 分解列表理解

修订版3

def perm(s):
    # Base case: an empty list or a list with only one item has only one
    # permutation
    if len(s) <= 1:
        return [s]

    # A list of permutations
    permutations = []
    # Recursively find all permutations of s[1:]
    for p in perm(s[1:]):
        for i in range(len(s)):
            # Insert s[0] in position i
            permutations.append(p[:i] + [s[0]] + p[i:])
    return permutations
  • 更改for循环的嵌套。现在,您可以说:对于每个排列,取每个排名i,然后在每个排名s[0] 中插入i添加该排列的副本。在接下来的几次修订中,这一点会更清晰。

修订版4

def perm(s):
    # Base case: an empty list or a list with only one item has only one
    # permutation
    if len(s) <= 1:
        return [s]

    # Recursively find all permutations of s[1:]
    shortperms = perm(s[1:])
    # A list of permutations
    permutations = []
    for shortperm in shortperms:
        for i in range(len(s)):
            # Make a copy of shortperm
            spcopy = shortperm[:]
            # Insert s[0] in position i
            spcopy.insert(s[0], i)
            # Add this to the list of permutations
            permutations.append(spcopy)
    return permutations
  • 移动perm函数调用。现在,shortperms变量将包含s[1:]的所有排列,即s减去第一项。
  • 将列表添加更改为三个操作:
    • 制作shortperm
    • 的副本
    • 在s
    • 中插入第一项
    • 将该列表添加到permutations

修订版5

def perm(s):
    # Base case: an empty list or a list with only one item has only one
    # permutation
    if len(s) <= 1:
        return [s]

    # Recursively find all permutations of s[1:]
    shortperms = perm(s[1:])
    # A list of permutations
    permutations = []
    for shortperm in shortperms:
        for i in range(len(shortperm) + 1):
            # Make a copy of shortperm
            spcopy = shortperm[:]
            # Insert s[0] in position i
            spcopy.insert(s[0], i)
            # Add this to the list of permutations
            permutations.append(spcopy)
    return permutations
  • len(s)len(shortperm) + 1相同,因为每个shortperm都是s中项目的排列,减去第一项。但是,这可能更具可读性。

最终代码

使用文档字符串注释

def perm(s):
    """Return a list of all permutations of the items in the input
    sequence."""
    # Base case: an empty list or a list with only one item has only one
    # permutation
    if len(s) <= 1:
        return [s]

    # Recursively find all permutations of s[1:]
    shortperms = perm(s[1:])
    # A list of permutations
    permutations = []
    for shortperm in shortperms:
        for i in range(len(shortperm) + 1):
            # Make a copy of shortperm
            spcopy = shortperm[:]
            # Insert s[0] in position i
            spcopy.insert(s[0], i)
            # Add this to the list of permutations
            permutations.append(spcopy)
    return permutations

答案 4 :(得分:0)

Python documentation for the itertools.permutations() function中有几个更容易消化的例子。请注意,此功能是Python 2.6中的新功能,因此如果您使用的是旧版本,则无法使用此功能。

SO谈话中也有很多例子和解释,这些例子和解释已经发生在不太遥远的过去,也代表了良好的阅读:

algorithm for python itertools.permutations

How to generate all permutations of a list in Python