Почему это делает Рэндом.перетасовать нет?


Почему random.shuffle возвращение None в python?

>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> print shuffle(x)
None

как мне получить перемешанное значение вместо None?

9 52

9 ответов:

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-функция аргумента, возвращающая случайный поплавок в [0.0, 1.0); by по умолчанию это функция random().

>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> shuffle(x)
>>> x
['bar', 'black', 'sheep', 'foo']

shuffle изменяет список на месте. Это хорошо, потому что копирование большого списка будет чистым накладным расходом, если вам больше не нужен исходный список.

по словам "явное лучше, чем неявное" принцип стиль для Python, возвращение списка было бы плохой идеей, потому что тогда можно было бы подумать, что это и новый, хотя на самом деле это не так.

если вы do нужен свежий список, вам придется напишите что-то вроде

new_x = list(x)  # make a copy
random.shuffle(new_x)

что хорошо ясно. Если вам часто нужна эта идиома, оберните ее в функцию shuffled (см. sorted), которая возвращает new_x.

У меня был момент aha с этой концепцией следующим образом:

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, которые изменяют структуру на месте сам возвращает нет как выходной.

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]