Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python通过for循环完成迭代后重新定义随机数列表的整个列表_Python_For Loop_Random - Fatal编程技术网

Python通过for循环完成迭代后重新定义随机数列表的整个列表

Python通过for循环完成迭代后重新定义随机数列表的整个列表,python,for-loop,random,Python,For Loop,Random,我已经使用Python几年了,不知道为什么它会以下面的方式运行。但也就是说,我不认为我曾经尝试过以这种特殊的方式处理随机数。请随时检查您的python(我使用3.5)是否以同样的方式运行 目标:我想生成一个列表列表,其中每个嵌套列表包含相同的值,但顺序不同 我有什么代码: import random # Define number slots opts = [1,2,3,4,5] li = [] for x in range(len(opts)): random.shuffle(op

我已经使用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循环在完成迭代之前一直按预期工作

带引导注释的代码: 结果:

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循环完成时或完成之后发生


你知道为什么吗?

你在一次又一次地向同一个列表添加引用


您可以在所有实例中看到上次洗牌的结果。

列表是可变的。这意味着,即使他们有一个身份,他们也可以有许多国家。您试图做的是将相同的列表附加几次,希望它们的当前状态保持不变。但实际上,每次重新洗牌时,该列表的所有实例都以相同的方式重新洗牌。改变一个会改变一切。您需要的是该列表的副本,一个您永远不会更改的副本,因此它将显示为冻结:

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
您正在反复洗牌同一个列表对象,并每次将其附加到
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]
这是与问题相同的问题

您可以使用副本解决此问题:

>>> 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
很大,或者其元素是大对象,那么最终可能会占用大量内存。如果这是一个问题,请考虑编写您自己的生成器(可能会混乱索引列表?)


在任何情况下,这都可以解释您所看到的行为。

您只有一个名为
opts
的列表-您将其洗牌多次,但这不会更改列表的标识。添加到
li
中的对该列表的所有引用仍然是对单个列表的引用。如果您同时查看它们,它们必然都具有相同的内容。如果您想随时间拍摄快照,请附加列表的副本(
li.Append(opts[:])
。如果您对范围(5)内的i执行
[id(li[i])
,则
li
的所有元素都引用相同的对象感谢您的解释!虽然使用copy的解决方案是正确的,但该解释误用了术语instance。您想说的是,对同一实例有多个引用,当它被洗牌时,这会反映在所有引用中。
>>> 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