为什么random.shuffle
在Python中返回None
?
>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> print shuffle(x)
None
如何获得洗牌值而不是None
?
random.shuffle()
改变了x
名单。
在原地改变结构的Python API方法通常返回None
,而不是修改后的数据结构。
如果你想创建一个基于现有列表的新随机混洗列表,现有列表按顺序保存,你可以使用random.sample()
和输入的全长:
x = ['foo', 'bar', 'black', 'sheep']
random.sample(x, len(x))
你也可以使用sorted()
和random.random()
作为排序键:
shuffled = sorted(x, key=lambda k: random.random())
但是这会调用排序(O(NlogN)操作),而对输入长度的采样只需要进行O(N)操作(使用与random.shuffle()
相同的过程,从收缩池中交换随机值)。
演示:
>>> import random
>>> x = ['foo', 'bar', 'black', 'sheep']
>>> random.sample(x, len(x))
['bar', 'sheep', 'black', 'foo']
>>> sorted(x, key=lambda k: random.random())
['sheep', 'foo', 'black', 'bar']
>>> x
['foo', 'bar', 'black', 'sheep']
这种方法也有效。
import random
shuffled = random.sample(original, len(original))
据docs说:
将序列x随机移动到位。可选参数random是一个0参数函数,在[0.0,1.0)中返回随机浮点数;默认情况下,这是函数random()。
>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> shuffle(x)
>>> x
['bar', 'black', 'sheep', 'foo']
shuffle
修改了列表。这很好,因为如果您不再需要原始列表,复制大型列表将是纯粹的开销。
根据pythonic style的“明确胜于隐性”原则,返回列表将是一个坏主意,因为那时人们可能认为它是一个新的,虽然实际上它不是。
如果你确实需要一个新的清单,你将不得不写一些类似的东西
new_x = list(x) # make a copy
random.shuffle(new_x)
这很明确。如果您经常需要这个习语,请将其包含在返回shuffled
的函数sorted
(请参阅new_x
)中。
我有这样一个概念:
from random import shuffle
x = ['foo','black','sheep'] #original list
y = list(x) # an independent copy of the original
for i in range(5):
print shuffle(y) # shuffles the original "in place" prints "None" return
print x,y #prints original, and shuffled independent copy
>>>
None
['foo', 'black', 'sheep'] ['foo', 'black', 'sheep']
None
['foo', 'black', 'sheep'] ['black', 'foo', 'sheep']
None
['foo', 'black', 'sheep'] ['sheep', 'black', 'foo']
None
['foo', 'black', 'sheep'] ['black', 'foo', 'sheep']
None
['foo', 'black', 'sheep'] ['sheep', 'black', 'foo']
shuffle(x)
不返回任何值。相反,该函数会自动改变变量。
所以不要试试
print shuffle(x)
而只是像这样打印变量。
>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> x
['bar', 'black', 'foo', 'sheep']
改变结构的Python API本身返回None作为输出。
list = [1,2,3,4,5,6,7,8]
print(list)
输出:[1,2,3,4,5,6,7,8]
from random import shuffle
print(shuffle(list))
输出:无
from random import sample
print(sample(list, len(list)))
输出:[7,3,2,4,5,6,1,8]
>> x = ['foo','bar','black','sheep']
>> random.shuffle(x)
>> print(x)
>> ['sheep', 'bar', 'foo', 'black']
正如所指出的,random.shuffle替换到位,因此您不需要新的列表变量。
您可以使用random.sample()
返回洗牌列表,如其他人所解释的那样。它的工作原理是从列表中抽取k个元素而无需替换。因此,如果列表中存在重复元素,则将对其进行唯一处理。
>>> l = [1,4,5,3,5]
>>> random.sample(l,len(l))
[4, 5, 5, 3, 1]
>>> random.sample(l,len(l)-1)
[4, 1, 5, 3]
>>> random.sample(l,len(l)-1)
[3, 5, 5, 1]