将对同一列表对象的多个引用附加到res。我们可以通过result = subsets([1, 2, 3])
print([id(u) for u in result])
这将打印8个相同ID的列表。在
因此,您对temp所做的各种更改都将“丢失”,并且res的最终内容将是对temp的最终值的8个引用,在本例中,它是空列表。在
解决此问题的简单方法是将temp的副本附加到res。在
^{pr2}$
输出[[], [1], [1, 2], [1, 2, 3], [1, 3], [2], [2, 3], [3]]
FWIW,我意识到这个练习的主要目的是练习递归,但是在Python中最好避免递归,除非您真的需要递归(例如,用于处理递归数据结构,如树)。但这里有一个更紧凑的迭代解决方案。在def subsets(seq):
z = [[]]
for x in seq:
z += [y + [x] for y in z]
return z
为了了解这是如何工作的,我们可以稍微扩展一下,并添加一个print调用。在def subsets(seq):
z = [[]]
for x in seq:
print('z =', z, 'x =', x)
w = []
for y in z:
w += [y + [x]]
z += w
return z
result = subsets([1, 2, 3])
print(result)
输出z = [[]] x = 1
z = [[], [1]] x = 2
z = [[], [1], [2], [1, 2]] x = 3
[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
我们从包含单个空列表的列表z开始。在
在每个循环中,我们创建一个新的列表w,方法是在z上循环,并使w中的每个项目成为{}中相应项的副本,并附加当前的x。然后我们用w的内容扩展z。在
为了好玩,这里有一个迭代生成器,它从位字符串(按自然顺序)生成子集。这种方法实际上是非常有效的,如果你想要一个大序列的所有子集而不消耗大量的RAM,这是很好的。在def subsets(seq):
w = len(seq)
for i in range(1<
yield [u for u, v in zip(seq, reversed('{:0{}b}'.format(i, w))) if v=='1']
print(*subsets([1, 2, 3]))
输出[] [1] [2] [1, 2] [3] [1, 3] [2, 3] [1, 2, 3]