
On Tue, Dec 29, 2020 at 10:30 AM Guido van Rossum <guido@python.org> wrote:
Interesting -- thanks for taking up the challenge. I still suspect that if we ran the corresponding benchmark at the C level, the first form would win,
I was thinking that might be the case -- but either way, there is little difference, and at least for ** unpacking, it's probably mostly used for small dicts anyway.
than the ABC)? -- that is, would **unpacking be able to use .items() and keys() be used in other contexts?
And why does ** unpacking need to check at all (LBYL) couldn't it simply do something like:
{k: d[k] for k in d}
I don't understand why LBYL is considered such an anti-pattern. It helps
Does there need to be a single defined "protocol" for a mapping (other produce much clearer error messages in this case for users who are exploring this feature, and distinguishing *early* between sequences and mappings is important for that.
Fair enough, though in this case, it's producing a not quite clear error message, whereas simply trying to call keys() would reflect the actual error. I was thinking about this a bit more, and realized that this pattern is used (at least) in the dict constructor and dict.update() -- but in both of those cases, they can take either a mapping or an iterable of (key, value) pairs. So it is required to make a distinction, and looking for keys() is as good a way as any (maybe the best, certainly well established) (and if you pass a object with a keys() method, but no __getitem__ into dict(), you get: "TypeError: 'MinMap' object is not subscriptable" -- not anything it about it needing to be a Mapping) But for **, which only supports Mappings, maybe there is no need to check for keys() -- it is clearly defined that iter(a_mapping) iterates over the keys, so that part should work, and if the __getitem__ doesn't work appropriately, then that's not really different than passing a iterable that doesn't produce valid (key, value) pairs to dict(). But this is all theoretical -- it's established, and a bit better docs should clear up the confusion. One more note on the docstrings: dict.update() says: "... If E is present and has a .keys() method..." Which nicely defines what is actually required. Whereas dict() says: "...dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs..." Without saying anything about how it determines what whether it's a mapping. So maybe that could be made a bit more clear as well. I also just noticed something else in the docs -- in typing, there is a Protocol type -- maybe we could/should pre-define a mapping protocol type? Or maybe a MinimialMapping ABC, analogous to the Iterable ABC -- though no idea what to call it that would be clear :-) -CHB -- Christopher Barker, PhD Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython