Sounds good to me.

If you want a second opinion als Raymond Hettinger.

On Wed, Jan 8, 2020 at 11:09 Bar Harel <bzvi7...@gmail.com> wrote:

> Well it depends on the consensus for __missing__, and the consensus for
> get().
>
> I believe modifying get() is out of the question as it will lead to
> breakage. If so, whether it's a quirk or not doesn't matter as we can't
> change it. Adding a comment to the docs should suffice, along with updating
> the data model to explicitly state dict.__missing__ instead of
> object.__missing__.
>
> As for __missing__, if it's only a dict thing, I don't believe Mapping
> should be aware of it's existence, which means the patch should center on
> UserDict behaving differently (thus mimicking dict's quirky behavior).
>
> Since we cannot override get() to access self.data, (as it will bypass and
> break custom __getitem__) I think we might as well modify it to use the
> __contains__ it already created.
>
> A simple check of "if k in D __getitem__" will slow only UserDict, not all
> mappings, and be an acceptable solution.
>
> That's all as long as we accept the 2 facts that __missing__ is dict-only
> and .get() will stay somewhat quirky and unexpected but documented.
>
> On Wed, Jan 8, 2020 at 8:11 PM Guido van Rossum <gu...@python.org> wrote:
>
>> Hum, it looks like the UserDict.get() behavior is an accident due to the
>> way Mapping.get() is implemented. The comment there says
>>
>>     'D.get(k[,d]) -> D[k] if k in D, else d.  d defaults to None.'
>>
>> but the implementation just tries D[k] and catches KeyError. The
>> UserDict.__contains__() implementation is explicitly code to avoid
>> __missing__, since the default Mapping.__contains__() implementation *also*
>> just calls D[k] and catches KeyError.
>>
>> More indication that the UserDict.get() behavior is an accident: in
>> test_userdict.py there's a test for __missing__, test_missing() but it
>> doesn't test get() at all, only __getitem__().
>>
>> How were you proposing to fix the situation? I could imagine changing
>> Mapping.get() to call __contains__() first. That would slow down
>> Mapping.get() slightly (the default implementation would end up calling
>> __getitem__() twice if the key is present), but I don't think that's a
>> grave concern (if people want it faster there are a zillion ways to do
>> that).
>>
>> On Wed, Jan 8, 2020 at 9:49 AM Bar Harel <bzvi7...@gmail.com> wrote:
>>
>>> 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 <gu...@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 <bzvi7...@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-le...@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)
>>>> *Pronouns: he/him **(why is my pronoun here?)*
>>>> <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
>>>>
>>>
>>
>> --
>> --Guido van Rossum (python.org/~guido)
>> *Pronouns: he/him **(why is my pronoun here?)*
>> <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
>>
> --
--Guido (mobile)
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@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/3ZHF6IEBE7PTJ6JAJQACVCOKUOAPEU5Y/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to