Почему random.shuffle
возвращает None
в python?
>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> print shuffle(x)
None
Как получить перетасованное значение вместо None
?
Почему random.shuffle
возвращает None
в python?
>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> print shuffle(x)
None
Как получить перетасованное значение вместо None
?
random.shuffle()
изменяет список x
на месте.
Методы API Python, которые изменяют структуру на месте, обычно возвращают 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-аргумент, возвращающий случайное значение float в [0.0, 1.0]; от default, это функция random().
>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> shuffle(x)
>>> x
['bar', 'black', 'sheep', 'foo']
shuffle
изменяет список на месте. Это хорошо, потому что копирование большого списка было бы чисто накладными расходами, если вам больше не нужен оригинальный список.
Согласно принципу "явно лучше, чем неявно" питонского стиля, возвращение списка было бы плохой идеей, потому что тогда можно подумать, что это новый, хотя на самом деле это не так.
Если вам нужен свежий список, вам придется написать что-то вроде
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]