On Sun, Jul 12, 2020 at 4:43 AM Christopher Barker firstname.lastname@example.org wrote:
The existing dictionary memory layout doesn't support direct indexing (without stepping), so this functionality is not being added as a requirement.
But it does make it much more efficient if the stepping is done inside the dict object by code that knows its internal structure. Both because it can be in C, and can be done without any additional references or copying. yes, it's all O(n) but a very different constant.
It's just a difference in proportional constants. If the performance difference is really important, dict_views must have `d.items().tolist()` (replacement for `list(d.items())`) before random indexing. It is much more used.
Currently, list(iterable) doesn't have any specialized algorithm for dict views. (As far as I know, it doesn't have specialized algorithm even for dict).
If random.choice should support non-sequence ordered container,
just propose it to random.choice.
That would indeed solve the usability issue, and so may be a good idea,
The problem here is that there is no way for random.choice to efficiently work with generic Mappings. This whole discussion started because now that dicts preserve order, there is both a logical reason, and a practical implementation for indexing. But if that is not exposed, then random.choice(), nor any other function, can take advantage of it.
Ditto. Iterating internal structure directly is not so important. And there is only little performance difference between current dict and previous dict implementation for iteration. I suppose new dict implementation is faster only 20~40%, when dict is clean (no item is removed yet).
So I don't think preserving order is good reason to support indexing while `random.choice` is the only use case.
Which would lead to adding a random_choice protocol -- but THAT sure seems like overkill. (OK, you could have the builtin random.choice check for an actual dict, and then use custom code to make a random selection, but that would really be a micro-optimization!)
I already wrote sample code using `itertools.islice()`. It works for all containers with len() and iterator. No need for adding protocol.
If a feature is useful, and doesn't conflict with another feature, then we can add it.
I believe this is a bad idea. It leads software to be huge, unmaintainable, and unusable. A Relatively high bar must be set for adding a feature to builtin type than adding a third party package on PyPI.