This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: random.shuffle pointlessly shuffles dicts
Type: behavior Stage: resolved
Components: Versions: Python 3.7
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: martin.panter, rhettinger, steven.daprano, tim.peters
Priority: normal Keywords:

Created on 2017-05-09 01:34 by steven.daprano, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Messages (4)
msg293265 - (view) Author: Steven D'Aprano (steven.daprano) * (Python committer) Date: 2017-05-09 01:34
According to the documentation, random.shuffle() should accept a sequence. But it also accepts dicts, in which case it does nothing, expensively:

py> x = dict.fromkeys(range(10**6))
py> random.shuffle(x)
py> str(x)[:55] + "...}"
'{0: None, 1: None, 2: None, 3: None, 4: None, 5: None, ...}'


I'm not sure if it is better to explicitly test for and reject dicts and mappings, or just document that sorting dicts will apparently succeed while doing nothing.

Do we want to support sorting OrderedDicts? That at least makes sense, since they have an order, but again shuffle() seemingly works but actually does nothing.

I lean towards explicitly testing for dicts and raising.
msg293266 - (view) Author: Martin Panter (martin.panter) * (Python committer) Date: 2017-05-09 01:58
It is also pointless to shuffle a list object repeating the same item, but that is no reason to add a special case. Is there a real problem with allowing dictionaries and OrderedDict? It seems to behave sensibly if you give each item a unique value:

>>> D = {i: i * 100 for i in range(5)}
>>> D
{0: 0, 1: 100, 2: 200, 3: 300, 4: 400}
>>> shuffle(D)
>>> D
{0: 300, 1: 100, 2: 200, 3: 0, 4: 400}
msg293269 - (view) Author: Tim Peters (tim.peters) * (Python committer) Date: 2017-05-09 02:29
Generally speaking, trying to shuffle a dict D already blows up, unless D's keys are the integers range(len(D)).  In that case, D is indistinguishable from a list in the sense that both map range(N) to values via __getitem__.  `shuffle()` does no type checks whatsoever now, and will shuffle any object that maps range(N) to values.

Fine by me the way it is.
msg293283 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2017-05-09 06:36
I concur with Tim.  These are just duck-typing facts of life.
History
Date User Action Args
2022-04-11 14:58:46adminsetgithub: 74496
2017-05-09 06:36:46rhettingersetstatus: open -> closed
resolution: not a bug
messages: + msg293283

stage: resolved
2017-05-09 02:29:38tim.peterssetnosy: + tim.peters
messages: + msg293269
2017-05-09 01:58:20martin.pantersetnosy: + martin.panter
messages: + msg293266
2017-05-09 01:34:22steven.dapranocreate