为什么我的powerset功能会耗尽内存?

时间:2017-12-17 21:42:52

标签: python powerset

def powerset(x):
    total1 = [[]]
    total2 = [[]]
    for a in x:
        for b in total1:
            c = list(b + [x[a]])
            total2.append(c)
        total1 = total2 
        # the total 1 and total 2 system should prevent it 
        # from creating an infinite loop when we add to the total.

        print (total1)

f = [1,2,3]
g = powerset(f)
print (g)

这是我尝试为数据科学课程的入门创建一个powerset。当我运行此命令时,我会在内存不足之前收到[[], [2]]作为输出。我不明白为什么它会返回[[], [2]],也不知道为什么它会耗尽内存,因为total1在循环之外被更改。

变量g应返回f

的幂集

有人可以解释我做错了吗?

1 个答案:

答案 0 :(得分:1)

在第一个循环后设置total1 = total2,这意味着 total1total2引用相同的列表

所以在第二个循环中,您迭代total1并更新total2,即同一个列表。在Python(以及大多数编程语言)中,更改迭代的集合是危险的,因此您不断向列表中添加项目,从而使循环越来越长。

代码本身并不存在问题。我们可以把它写成:

def powerset(x):
    result = [[]]
    for xi in x:
        xil = [xi]
        for j in range(len(result)):
            result.append(result[j] + xil)
    return result

虽然它可能看起来像是一些语法重写,但我们在j上迭代range(len(result))。请注意,我们只计算len(result) 一次,当我们启动for循环时,之后,我们可以安全地更新total,因为范围对象不会改变了。

然后产生:

>>> powerset([1,2,3])
[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]

请注意,我们可以使用itertools.combinations函数来简化生活:

from itertools import combinations

def powerset(x):
    xl = list(x)
    for r in range(len(xl)+1):
        for ri in combinations(xl, r):
            yield ri

然后我们获得:

>>> list(powerset([1,2,3]))
[(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)]