我已经使用Python几年了,不知道为什么它会以以下方式运行。但这就是说,我认为我从未尝试过以这种特殊方式处理随机数。请随时检查您的python(我使用3.5)是否以相同的方式运行。
目标:我想生成一个列表列表,其中每个嵌套列表都包含相同的值,但顺序不同。
我拥有什么代码:
import random
# Define number slots
opts = [1,2,3,4,5]
li = []
for x in range(len(opts)):
random.shuffle(opts) # Jumbles the options list
li.append(opts) # Append that list to the parent list
因此,我声明了一个包含所需值的选项列表。然后,我使用random.shuffle()混合列表。然后将其附加到主列表。但是当我检查结果时,每个嵌套列表都有相同的数字排序列表...
>>> for each in li:
print(each)
[5, 4, 2, 1, 3]
[5, 4, 2, 1, 3]
[5, 4, 2, 1, 3]
[5, 4, 2, 1, 3]
[5, 4, 2, 1, 3]
>>>
本来我的代码比上面的复杂,但是由于我之前没有在python中广泛地使用伪随机数,所以我认为我不完全了解随机方法。因此,我一直在使代码变得越来越简单。但是结果是一样的。因此,我终于发现for循环可以按预期工作,直到完成迭代为止。
import random
# Define number slots
opts = [1,2,3,4,5]
li = []
print("Now defining the list: \n")
for x in range(len(opts)):
random.shuffle(opts) # Jumble the options list
li.append(opts) # Append that list
print("li[{}] = {}".format(x,li[x])) # Outputs list associated with index
print("\nNow print each index:")
for y in range(len(li)):
print("li[{}] = {}".format(y,li[y]))
结果:
Now defining the list:
li[0] = [3, 4, 2, 5, 1]
li[1] = [2, 1, 5, 3, 4]
li[2] = [1, 5, 2, 3, 4]
li[3] = [5, 1, 2, 4, 3]
li[4] = [2, 1, 5, 3, 4]
Now print each index:
li[0] = [2, 1, 5, 3, 4]
li[1] = [2, 1, 5, 3, 4]
li[2] = [2, 1, 5, 3, 4]
li[3] = [2, 1, 5, 3, 4]
li[4] = [2, 1, 5, 3, 4]
因此,第一个输出部分反映了每个附加的嵌套列表。输出的第二个块反映出相同的内容,但是在for循环完成其迭代之后。
我茫然为什么会这样。由于某种原因,每个嵌套列表都更改为最后一个附加列表,但必须在for循环完成时或之后发生。
有什么想法吗?
答案 0 :(得分:4)
列表是可变的。这意味着即使它们具有一个身份,它们也可以具有许多状态。您尝试做的是将同一列表添加几次,希望它们的当前状态保持这种状态。但实际上,每次重新洗牌时,该列表的 all 实例都以相同的方式洗牌。改变一个改变它们。您想要的是该列表的副本,您永远都不会更改它,因此它将显示为冻结状态:
for x in range(len(opts)):
copy = opts.copy() # make a copy
random.shuffle(copy) # shuffle only the copy
li.append(copy) # append only the copy
答案 1 :(得分:1)
您要反复对 same 列表对象进行改组,并将其每次附加到li
列表中。请注意,子列表的ID都是一样的:
>>> import random
>>> opts = [1,2,3,4,5]
>>> li = []
>>> for x in range(len(opts)):
... random.shuffle(opts)
... li.append(opts)
...
>>> li
[[1, 3, 4, 5, 2], [1, 3, 4, 5, 2], [1, 3, 4, 5, 2], [1, 3, 4, 5, 2], [1, 3, 4, 5, 2]]
>>> [id(item) for item in li]
[4392262856, 4392262856, 4392262856, 4392262856, 4392262856]
这与mutable default argument "gotcha"一样。
您可以使用副本解决此问题:
>>> import random
>>> opts = [1,2,3,4,5]
>>> li = []
>>> for x in range(len(opts)):
... new_list = opts.copy()
... random.shuffle(new_list)
... li.append(new_list)
...
>>> li
[[4, 1, 2, 5, 3], [3, 5, 2, 4, 1], [3, 2, 1, 5, 4], [5, 2, 4, 1, 3], [1, 3, 5, 4, 2]]
>>> [id(item) for item in li]
[4392411016, 4392262856, 4392410952, 4392399112, 4392399048]
>>> id(opts)
4392411080
请注意,如果opts
大或它的元素是大对象,则可能会占用大量内存。如果有问题,可以考虑编写自己的生成器(也许改组索引列表?)。
无论如何,这可以解释您所看到的行为。
答案 2 :(得分:0)
您要一遍又一遍地向同一列表添加引用。
您会看到在所有实例中镜像的最后一次随机播放的结果。