There is a restriction on random.choice
that the input must be a sequence. This causes non-obvious and hairy behaviour on a dict
:
>>> d = {0: 'spam', 1: 'eggs', 3: 'potato'}
>>> random.choice(d)
'spam'
>>> random.choice(d)
'eggs'
>>> random.choice(d)
'spam'
>>> random.choice(d)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/random.py", line 274, in choice
return seq[int(self.random() * len(seq))] # raises IndexError if seq is empty
KeyError: 2
Additionally it doesn't work at all on a set
, and some other containers in collections
module.
Aside from my opinion that this implementation of random.choice
is balls (there is no good reason why random.choice(d)
shouldn't just work in the obvious way), what is a pythonic way to get a random choice from a non-sequence collection?
I considered random.choice(list(d))
and random.sample(d, 1)[0]
but hope there may be other less ugly methods.
Can random.choice
be monkey-patched to 'just work' while not breaking or drastically reducing efficiency of the current behaviour on sequences?
You can see this thread on the Python bug tracker from 2006 about random.choice not working for sets. It's algorithmically possible to make it work with the same asymptotic efficiency, but it would require either custom support from the set/dict data structures, or a new method in the interface. The python devs don't deem it needed.