# Why does random.shuffle return None?

Each Answer to this Q is separated by one/two green lines.

Why is `random.shuffle` returning `None` in Python?

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

How do I get the shuffled value instead of `None`?

`random.shuffle()` changes the `x` list in place.

Python API methods that alter a structure in-place generally return `None`, not the modified data structure.

``````>>> x = ['foo', 'bar', 'black', 'sheep']
>>> random.shuffle(x)
>>> x
['black', 'bar', 'sheep', 'foo']
``````

If you wanted to create a new randomly-shuffled list based on an existing one, where the existing list is kept in order, you could use `random.sample()` with the full length of the input:

``````random.sample(x, len(x))
``````

You could also use `sorted()` with `random.random()` for a sorting key:

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

but this invokes sorting (an O(N log N) operation), while sampling to the input length only takes O(N) operations (the same process as `random.shuffle()` is used, swapping out random values from a shrinking pool).

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']
``````

This method works too.

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

# Why, really?

## 1. Efficiency

`shuffle` modifies the list in place.
This is nice, because copying a large list would be pure overhead if you do not need the original list anymore.

## 2. Pythonic style

According to the “explicit is better than implicit” principle of pythonic style, returning the list would be a bad idea, because then one might think it is a new one although in fact it is not.

## But I don’t like it like this!

If you do need a fresh list, you will have to write something like

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

which is nicely explicit.
If you need this idiom frequently, wrap it in a function `shuffled` (see `sorted`) that returns `new_x`.

According to docs:

Shuffle the sequence x in place. The optional argument random is a
0-argument function returning a random float in [0.0, 1.0); by
default, this is the function random().

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

I had my aha moment with this concept like this:

``````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']
``````

The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 .