Python 为什么我的powerset函数内存不足?

Python 为什么我的powerset函数内存不足?,python,powerset,Python,Powerset,下面是我为数据科学入门课程创建动力集的尝试。当我运行这个程序时,在内存耗尽之前,我会收到[[],[2]]作为输出。我不明白它为什么返回[[],[2]],也不明白它为什么会耗尽内存,因为total1是在循环之外更改的 变量g应返回f的幂集 有人能解释一下我做错了什么吗?在第一个循环之后,您设置了total1=total2,这意味着total1和total2引用的是同一个列表 因此在第二个循环中,您迭代total1并更新total2,相同的列表。在Python和大多数编程语言中,修改迭代的集合是危险

下面是我为数据科学入门课程创建动力集的尝试。当我运行这个程序时,在内存耗尽之前,我会收到[[],[2]]作为输出。我不明白它为什么返回[[],[2]],也不明白它为什么会耗尽内存,因为total1是在循环之外更改的

变量g应返回f的幂集


有人能解释一下我做错了什么吗?

在第一个循环之后,您设置了total1=total2,这意味着total1和total2引用的是同一个列表

因此在第二个循环中,您迭代total1并更新total2,相同的列表。在Python和大多数编程语言中,修改迭代的集合是危险的,因此不断向列表中添加项,使循环越来越长

代码本身并没有问题。我们可以这样写:

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)
虽然它看起来像是一些语法重写,但我们在这里对结果进行迭代。请注意,当我们启动for循环时,我们只计算一次lenresult,因此在这之后,我们可以安全地更新total,因为range对象不再更改

这将产生:

def powerset(x):
    result = [[]]
    for xi in x:
        xil = [xi]
        for j in range(len(result)):
            result.append(result[j] + xil)
    return result
请注意,我们可以使用itertools.combinations函数简化操作:

>>> powerset([1,2,3])
[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
然后我们获得:

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

对于x中的a,不在索引上迭代,而是在x中的元素上迭代。对于大小为n的集合,电源集的大小为2**n。这是非常快的,并且在一组30个元素中会达到略多于10亿。这可能超出了问题的范围,但我的印象是当你将两者等同时,它们不会一起更新,即a=1,b=a,b+=1,打印a打印1而不是2?这是因为int是不可变的,因此Python在添加时会后退。列表是可变的。
>>> list(powerset([1,2,3]))
[(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)]