
On Thu, Jul 09, 2020 at 06:26:41PM +0100, Stestagg wrote:
As for use-cases, I'll admit that I see this as a fairly minor quality-of-life issue.
Thank you for that comment. I too have sometimes proposed what I think of as "minor quality-of-life" enhancements, and had them shot down. It stings a bit, and can be frustrating, but remember it's not personal. The difficulty is that our QOL enhancement is someone else's bloat. Every new feature is something that has to be not just written once, but maintained, documented, tested and learned. Every new feature steepens the learning curve for the language; every new feature increases the size of the language, increases the time it takes to build, increases the time it takes for the tests to run. This one might only be one new method on three classes, but it all adds up, and we can't add *everything*. (I recently started writing what was intended to be a fairly small class, and before I knew it I was up to six helper classes, nearly 200 methods, and approaching 1500 LOC, for what was conceptually intended to be a *lightweight* object. I've put this aside to think about it for a while, to decide whether to start again from scratch with a smaller API, or just remove the word "lightweight" from the description :-) So each new feature has to carry its own weight. Even if the weight in effort to write, effort to learn, code, tests and documentation is small, the benefit gained must be greater or it will likely be rejected. "Nice to have" is unlikely to be enough, unless you happen to be one of the most senior core devs scratching your own itch, and sometimes not even then.
import numpy as np mapping_table = np.array(BIG_LOOKUP_DICT.items()) [[1, 99], [2, 23], ... ]
That worked in Python 2 by making a copy of the dict items into a list. It will equally work in Python 3 by making a copy of the items into a list. And I expect that even if dict.items() was indexable, numpy would still have to copy the items. I don't know how numpy works in detail, but I doubt that it will be able to use a view of a hash table internals as a fast array without copying. Bottom line here is that adding indexing to dict views won't save you either time or memory or avoid making a copy in this example. All it will save you is writing an explicit call to `list`. And we know what the Zen says about being explicit.
import sqlite3 conn = sqlite3.connect(":memory:") params = {'a': 1, 'b': 2} placeholders = ', '.join(f':{p}' for p in params) statement = f"select {placeholders}" print(f"Running: {statement}") Running: select :a, :b cur=conn.execute(statement, params.values()) cur.fetchall() [(1, 2)]
Why are you passing a view to a values when you could pass the dict itself? Is there some reason you don't do this? # statement = "select :a, :b" py> cur=conn.execute(statement, params) py> cur.fetchall() [(1, 2)] I'm not an expert on sqlite, so I might be missing something here, but I would have expected that this is the prefered solution. It matches the example in the docs, which uses a dict.
# This currently works, but is deprecated in 3.9
dict(random.sample({'a': 1, 'b': 2}.items(), 2)) {'b': 2, 'a': 1}
I suspect that even if dict items were indexable, Raymond Hettinger would not be happy with random.sample on dict views.
def min_max_keys(d): min_key, min_val = d.items()[0] max_key, max_val = min_key, min_val for key, value in d.items():
Since there's no random access to the items required, there's not really any need for indexing. You only need the first item, then iteration. So the natural way to write that is with iter() and next(). I suspect that the difference in perspective here is that (perhaps?) you still thing of concrete sequences and indexing as fundamental, while Python 3 has moved in the direction of making the iterator protocol and iterators as fundamental. You have a hammer (indexing), so you want views to be nails so you can hammer them. But views are screws, and need a screwdriver (iter and next). I'm not disputing that sometimes a hammer is the right solution, I'm just dubious that having views be a mutant nail+screw hybrid is worth it, just so you can pass a view to random.sample.
The idea that there are future, unspecified changes to dicts() that may or may not be hampered by allowing indexing sounds like FUD to me, unless there are concrete references?
Nobody is suggesting that dicts will cease to be order preserving in the future. But order preserving does not necessarily require there to be easy indexing. It just requires that the order of iteration is the same as order of insertion, not that we can jump to the 350th key without stepping through the previous 349 keys. Dicts have gone through a number of major redesigns and many careful tweaks over the years to get the best possible performance. The last major change was to add *order-preserving* behaviour, not indexing. The fact that they can be indexed in reasonable time is not part of the design, just an accident of implementation, and being an accident, it could change in the future. This feature would require upgrading that accident of implementation to a guarantee. If the Python world were awash with dozens of compelling, strong use-cases for indexing dicts, then we would surely be willing to make that guarantee. But the most compelling use-case we've seen so far is awfully weak indeed: choose a random item from a dict. So the cost-benefit calculation goes (in my opinion) something like this. 1. Risk of eliminating useful performance enhancements in the future: small. 2. Benefit gained: even smaller. That's not FUD. It's just a simple cost-benefit calculation. You can counter it by finding good use-cases that are currently difficult and annoying to solve. Using an explicit call to list is neither difficult nor annoying :-) -- Steven