¿Por qué random.shuffle
regresa None
en Python?
>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> print shuffle(x)
None
¿Cómo obtengo el valor barajado en lugar de None
?
¿Por qué random.shuffle
regresa None
en Python?
>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> print shuffle(x)
None
¿Cómo obtengo el valor barajado en lugar de None
?
Respuestas:
random.shuffle()
cambia la x
lista en su lugar .
Los métodos de la API de Python que alteran una estructura en el lugar generalmente devuelven None
, no la estructura de datos modificada.
Si desea crear una nueva lista aleatoria basada en una existente, donde la lista existente se mantiene en orden, puede usar random.sample()
con la longitud completa de la entrada:
x = ['foo', 'bar', 'black', 'sheep']
random.sample(x, len(x))
También puede usar sorted()
con random.random()
para una clave de clasificación:
shuffled = sorted(x, key=lambda k: random.random())
pero esto invoca la clasificación (una operación O (NlogN)), mientras que el muestreo a la longitud de entrada solo toma operaciones O (N) (el mismo proceso que random.shuffle()
se usa, intercambiando valores aleatorios de un grupo que se reduce).
Manifestación:
>>> 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']
key
realmente garantizado el uso de una función de valor aleatorio ? Algunos algoritmos de clasificación rápida fracasan si las comparaciones no son autoconsistentes. Puedo ver que esto funciona de cualquier manera, dependiendo de la implementación (decorate-sort-undecorate solo deberá aplicarse key
una vez en cada elemento, por lo que estará bien definido).
key
invocable. Así que sí, está garantizado ya que a cada valor se le da su clave aleatoria exactamente una vez.
Según los documentos :
Mezcla la secuencia x en su lugar. El argumento opcional aleatorio es una función de argumento 0 que devuelve un flotante aleatorio en [0.0, 1.0); por defecto, esta es la función aleatoria ().
>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> shuffle(x)
>>> x
['bar', 'black', 'sheep', 'foo']
shuffle
modifica la lista en su lugar. Esto es bueno, porque copiar una lista grande sería una sobrecarga si ya no necesita la lista original.
Según el principio "explícito es mejor que implícito" del estilo pitónico , devolver la lista sería una mala idea, porque entonces se podría pensar que es nueva aunque en realidad no lo es.
Si usted no necesita una nueva lista, tendrá que escribir algo como
new_x = list(x) # make a copy
random.shuffle(new_x)
que es muy explícito. Si necesita este modismo con frecuencia, envuélvalo en una función shuffled
(ver sorted
) que devuelva new_x
.
Tuve mi momento aha con este concepto como este:
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']
Las API de Python que cambian la estructura en su lugar devuelven None como resultado.
list = [1,2,3,4,5,6,7,8]
print(list)
Salida: [1, 2, 3, 4, 5, 6, 7, 8]
from random import shuffle
print(shuffle(list))
Salida: ninguna
from random import sample
print(sample(list, len(list)))
Salida: [7, 3, 2, 4, 5, 6, 1, 8]
Puede devolver la lista aleatoria utilizando random.sample()
como explicaron otros. Funciona muestreando k elementos de la lista sin reemplazo . Entonces, si hay elementos duplicados en su lista, se tratarán de manera única.
>>> 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]