函数内部的函数,Python中列表的递归。

4
def minimizeMaximumPair(lst):
    lst.sort()

    def compute(aList):
        if len(aList) != 0:
            return [(aList[0], lst[len(aList) - 1])].extend(compute(aList[1:len(aList) - 1]))
        return []

    return compute(lst)

当我到达最后一步递归时,我遇到了一个


TypeError: 'NoneType' object is not iterable

我尝试返回空值和一个 []。
3个回答

4
问题出现在您调用 .extend() 函数时。
您的函数 compute 尝试返回 .extend() 的值,但是它的返回值是None。类似于 .sort().extend() 修改的是对象本身,而不是返回修改后的对象副本。这就是所谓的可变性。下面是一些可行的代码:
def compute(aList):
    if len(aList) != 0:
        out = [(aList[0], lst[len(aList) - 1])]
        out.extend(compute(aList[1:len(aList) - 1]))
        return out
    return []

我猜我可以倒着写,因为:<not copied>.extend(<copied>),对吧? - Maxime Roussin-Bélanger
@MaximeRoussin-Bélanger,是的,你应该能够做到。 - Zizouz212

3

不要使用返回Nonelist.extend,可以使用list.__iadd__

__iadd__ 也是原地扩展列表,但之后会返回list

如果您不喜欢使用特殊方法,可以使用operator模块中的iadd

from operator import iadd

...

def compute(aList):
    if len(aList) != 0:
        return iadd([(aList[0], aList[-1])], compute(aList[1: -1]))
    return []

这有点毫无意义。为什么我们需要调用一个“特殊”的方法?这个问题更多的是对所使用方法行为的误解。 - Zizouz212
@Zizouz212,不是很对。如果你正在编写函数式代码,你需要了解这个,否则你会重复已经成为语言一部分的代码。 - John La Rooy
我将递归调用更改为更简单的方式,但使用了您的解决方案:iadd([(aList [0],aList [-1])],compute(aList [1:-1]))。 - Maxime Roussin-Bélanger
@MaximeRoussin-Bélanger,很酷,我更新了我的答案。现在-你仍然使用aList[1: -1]进行部分复制。如果您需要更好的性能,应该考虑传递额外的参数来表示第一个和最后一个索引,而不是实际切片列表。 - John La Rooy

1
那是因为extend是一个不返回任何东西的函数,它只是在原地改变列表。一个可能的解决方案是使用+代替:
return [(aList[0], lst[len(aList) - 1])] + compute(aList[1:len(aList) - 1])

1
这会导致每次复制第一个列表,而不是仅扩展现有列表。 - John La Rooy
1
真的,但也是最干净的解决方案。 - BrunoRB
2
也许是这样,但是当一层又一层地叠加时,这种态度会导致大型程序的许多缓慢。 - John La Rooy

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