Python 使用随机模块创建嵌套列表

Python Creating a nested list with random module

假设我想创建一个带有数字序列的嵌套列表,并且我不想要重复的列表序列。

即我想要这样的东西: [[1,2,3,4],[2,1,3,4],[4,2,3,1]] ,其中列表的 len 取决于我可以在有限的尝试中生成多少个非重复数字序列(在下面的情况下尝试四次)

这是我的第一次尝试:

import random
rng = random.Random()
bd =list(range(4))
i = 0
result =[]

while i <4:
    rng.shuffle(bd)
    if bd not in result:
        result.append(bd)
    i +=1
print(result)

我在进入 while 循环之前先创建了一个列表 bd = [0,1,2,3]

虽然 运行 上面的代码,但令人惊讶的是,每次我的嵌套列表中都只有一个元素。

结果:[[1, 2, 0, 3]]

但是如果我稍微修改一下代码,它就会按我预期的那样工作。 这是我修改后的代码:

import random
rng = random.Random()
i = 0
result =[]

while i <4:
    bd =list(range(4))
    rng.shuffle(bd)
    if bd not in result:
        result.append(bd)
    i +=1
print(result)

结果:[[3, 2, 0, 1], [1, 0, 3, 2], [0, 1, 3, 2]]

我所做的只是在每个循环中重新设置列表 bd

根据我的理解,列表 bd 将在每个循环中被洗牌,因此将 bd 重置为 [0,1,2,3] 应该没有意义。 有人可以向我解释为什么修改后的代码有效吗?谢谢。

在您的第一次尝试中,您每次都将 相同的 列表改组并附加到结果中。尝试通过获取整个列表的一部分来使用副本:bd[:] 是一个完全独立的对象,当您在下一次循环中打乱原始 bd 时,它不会改变。

import random
rng = random.Random()
bd =list(range(4))
i = 0
result =[]

while i <4:
    rng.shuffle(bd)
    if bd not in result:
        result.append(bd[:])
    i +=1
print(result)

输出:

[[2, 1, 3, 0], [1, 2, 3, 0], [0, 3, 2, 1]]

Python 中的列表和类似对象通过引用引用。考虑以下简单示例:

a_list = [1,2,3,4,5]
another_list = []

for i in range(5):
    another_list.append(a_list)
    a_list[0] = i + 10

print(another_list)

您希望输出为:

[[10, 2, 3, 4, 5], [11, 2, 3, 4, 5], [12, 2, 3, 4, 5], [13, 2, 3, 4, 5], [14, 2, 3, 4, 5]]

然而,您看到的输出是:

[[14, 2, 3, 4, 5], [14, 2, 3, 4, 5], [14, 2, 3, 4, 5], [14, 2, 3, 4, 5], [14, 2, 3, 4, 5]]

每次调用 another_list.append(a_list) 时,都会将 reference 附加到 a_list。然后您更改 a_list,之前附加的引用指向更改后的列表。

最后,a_list 等于 [14, 2, 3, 4, 5],并且 another_list 包含对该列表的五个相同引用。


回到你的案例。为防止这种情况发生在您身上,您可以在每次追加列表时创建一个副本,as documented here:

import random
rng = random.Random()
i = 0
result =[]

while i <4:
    bd =list(range(4))
    rng.shuffle(bd)
    if bd not in result:
        # Use [:] to create a slice of bd which actually contains the whole list
        result.append(bd[:])
    i +=1
print(result)

发生这种情况是因为您将 bd 附加到 result 并在下一次迭代中使用 bd,它们具有相同的引用。
在第二个中,您在每次迭代中生成一个新列表(不同的引用)。

您的代码有一个小问题:shuffle 执行就地更改,因此它更改了您的变量引用的对象。通过运行第一个代码,你总是会得到一个结果——最后的洗牌操作。为避免这种情况,您应该附加一份 list:

import random
rng = random.Random()
bd =list(range(4))
i = 0
result =[]

while i <4:
    rng.shuffle(bd)
    if bd not in result:
        result.append(bd[:])
    i +=1
print(result)