2013-07-15 10 views
45

Warum gibt random.shuffle in Python None zurück?Warum kehrt random.shuffle zurück?

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

Wie bekomme ich den gemischten Wert statt None?

+0

nicht zufälliger Wert, aber zufälliges Mischen der Liste. – alvas

+2

Zugehörige: [sort() und reverse() funktionieren nicht] (http://stackoverflow.com/q/16460616) –

Antwort

71

random.shuffle() ändert die x Liste an Ort und Stelle.

Python-API-Methoden, die eine vorhandene Struktur ändern, geben im Allgemeinen None zurück, nicht die geänderte Datenstruktur.

Wenn Sie eine neue zufällig gemischt Liste anhand eines bestehenden, in der bestehenden Liste gehalten wird, um erstellen wollten, Sie random.sample() mit der vollen Länge der Eingabe verwenden:

x = ['foo', 'bar', 'black', 'sheep'] 
random.sample(x, len(x))  

Sie könnten auch sorted() mit random.random() für einen Sortierschlüssel verwenden:

shuffled = sorted(x, key=lambda k: random.random()) 

aber dies ruft Sortierung (eine O (NlogN) Betrieb), während auf der inpu Abtasten Die Länge dauert nur O (N) -Operationen (der gleiche Prozess wie random.shuffle() wird verwendet, zufällige Werte aus einem schrumpfenden Pool auszuwechseln).

Demo:

>>> 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'] 
+0

Was ist '.pop()'? Das entfernt den angegebenen Index aus einer Liste und gibt das Element zurück, oder fehlt mir etwas – TerryA

+0

@Haidro: sicher, '.pop()' ist explizit als Rückgabe des entfernten Elements dokumentiert. Die Formulierung wurde angepasst. –

+2

Ist die Verwendung einer zufälligen Schlüsselfunktion wirklich garantiert? Einige schnelle Sortieralgorithmen fallen um, wenn Vergleiche nicht selbstkonsistent sind. Ich kann sehen, dass dies in beiden Richtungen funktioniert, abhängig von der Implementierung (decorate-sort-undecorate muss nur 'key' einmal auf jedes Element anwenden, so dass es gut definiert ist). – torek

6

Nach docs:

Mische die Sequenz x an seinem Platz. Das optionale Argument random ist eine 0-Argument-Funktion, die einen zufälligen Gleitkommawert in [0.0, 1.0] zurückgibt; von Standard ist dies die Funktion random().

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

shuffle ändert die Liste an seinem Platz. Das ist nett, weil das Kopieren einer großen Liste reiner Overhead wäre, wenn Sie die ursprüngliche Liste nicht mehr benötigen.

Nach dem „explicit ist besser als impliziten“ Prinzip der pythonic style, wäre eine schlechte Idee, die Liste zurückkehrt, denn dann man denken könnte, es ist ein neues Geschäft, obwohl in der Tat ist es nicht.

Wenn Sie eine neue Liste tun müssen, werden Sie so etwas wie

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

schreiben, die schön explizit ist. Wenn Sie dieses Idiom häufig benötigen, wickeln Sie es in eine Funktion shuffled (siehe sorted), die new_x zurückgibt.

23

Ich denke diese Methode funktioniert auch.

import random 
shuffled = random.sample(original, len(original)) 
1

hatte ich mein Aha-Moment mit diesem Konzept so:

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'] 
+0

Weil Python standardmäßig "copy-by-values" anstelle von pass-by-reference =) http://stackoverflow.com/a/986495/610569 – alvas

1
shuffle(x) 

liefert keine Werte. Stattdessen mischt diese Funktion die Variable selbst.

versuchen Sie also nicht

print shuffle(x) 

stattdessen nur die Variable wie folgt zu drucken.

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