Sorry for the double post then :-)

As for get(). Current implementation of UserDict returns the default value for get() if __missing__() raises KeyError. Which sounds reasonable to me. After all, you would logically expect __missing__ to be called for get() as you tried to get a non-existing value.

If __missing__ is only a dict thing, then I'll add a note to dict's .get() method saying it doesn't call __missing__ for missing values.
I can also modify UserDict to behave in a consistent manner.

Does that make sense?

On Wed, Jan 8, 2020 at 7:42 PM Guido van Rossum <guido@python.org> wrote:
(Note: We received your email twice.)

I don't think __missing__ should be called by get() -- get() already has a way to deal with missing keys, and making it use two different mechanisms would be weird (e.g. if get() calls __missing__, is the default value ever used?).

To answer your second question, __missing__ is only a dict thing, it is not part of Mapping.

On Wed, Jan 8, 2020 at 8:07 AM Bar Harel <bzvi7919@gmail.com> wrote:
Hey guys,

I was just about to fix dict's get() to call __missing__ if a key doesn't exist (before returning the default value) but realized that although small, that patch can cause future issues.
Right now there's an inconsistency:

>>> from collections import UserDict
>>> class A(dict):
...  def __missing__(self, key):
...   print(key)
...
>>> class B(UserDict):
...  def __missing__(self, key):
...   print("UserDict", key)
...
>>> a = A()
>>> b = B()
>>> a.get(123)
>>> b.get(123)
UserDict 123
>>> a.get(123, "abc")
'abc'
>>> b.get(123, "abc")
UserDict 123

The reason for this inconsistency is because the Mapping abc and dict behave differently.
Dict's get doesn't call __getitem__ which causes the call not to route to __missing__.
MutableMapping's get calls __getitem__, which UserDict implements as a check to __missing__ as well.

According to the doc, the specification requires dict's __getitem__ to call __missing__. It doesn't say anything about get().

Should get() call __missing__?

If it does, things like defaultdict.get() might break. It will however be more consistent with dict's specification.
If it doesn't, we expect Mapping to not care about __missing__ as it's only a dict thing, which will require UserDict to override get(). Dict's get() will need to receive a doc update as well stating __missing__ is not called.

Second question is: Is __missing__ only a dict thing, or is it part of the Mapping ABC?

I would expect it to be a part of the Mapping ABC, with subclasses not having to implement it. Right now it's not.

Looking forward for your inputs,
Bar Harel
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/SDXOEMAEM6KQ3CQCJVBVRT5QNSPAVU6X/
Code of Conduct: http://python.org/psf/codeofconduct/


--
--Guido van Rossum (python.org/~guido)