Why Does Random.Shuffle Return None

Why does random.shuffle return 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']

Python - Random.shuffle returns nonetype instead of list whereas random.choice returns str or int

How to change the nonetype to List type

You don't. Realise what it means for a method to apply an in place algorithm: it means that the result is available in the variable that you have provided as argument. There is no need to assign it, as you already have it: the variable you passed as argument has the result. See also the answers to your previous question.

Why there is a difference in behaviors of two different methods. What is the rule and the logic behind the rule?

There is indeed a logic as to why these methods were designed like that:

If the method intends to mutate an argument, then it should not return anything other than None

So in this particular case we have random.choice. This method is not about mutating a list. It is a "read-only" method, that just chooses an element from a given list. There is no mutation going on, and no new object is created. It merely uses what is already there. So this is the perfect situation for returning the result.

On the other hand we have random.shuffle. This method suggests (by its name) that it will rearrange the given list (randomly): that is a mutation. The same can be said about sort: it also mutates the list on which that method is called. So here the principle is to not return anything. If the name of the method were random.shuffled, then it would have been a different story: that name suggests you would get a variant of the given list that is rearranged; in other words: a new list would be made. In that case, the original list would not be mutated, and it would be appropriate for the new list to be the returned value. This method does not exist, but the same idea does exist for sorting: sorted returns a new list.

I hope this explains why the language designers have designed these methods to work like that.

numpy.random.shuffle returns None

shuffle works in place and therefore does not return a value.

In [1]: x = range(9)

In [2]: x
Out[2]: [0, 1, 2, 3, 4, 5, 6, 7, 8]

In [5]: print numpy.random.shuffle(x)
None

In [6]: x
Out[6]: [8, 7, 3, 4, 6, 0, 5, 1, 2]

Random shuffle list becomes None

random.shuffle works in-place, it does not return anything (And hence by default it returns None , since all Python function calls should return some value) , hence when you do - a = random.shuffle(a) , a becomes None. Try -

random.shuffle(a)

From documentation of random.shuffle -

random.shuffle(x[, random])

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().

(Emphasis mine)

Shuffling a list of objects

random.shuffle should work. Here's an example, where the objects are lists:

from random import shuffle

x = [[i] for i in range(10)]
shuffle(x)
print(x)

# print(x) gives [[9], [2], [7], [0], [4], [5], [3], [1], [8], [6]]

Note that shuffle works in place, and returns None.

More generally in Python, mutable objects can be passed into functions, and when a function mutates those objects, the standard is to return None (rather than, say, the mutated object).



Related Topics



Leave a reply



Submit