[Python-Dev] Possible wrong behavior of the dict?

Zaur Shibzukhov szport at gmail.com
Tue Mar 17 20:45:50 CET 2015


So in such cases it should not subclassed `dict`, but
`collections.MutableMapping`, for example?

---
*Zaur Shibzukhov*


2015-03-17 22:38 GMT+03:00 Brett Cannon <brett at python.org>:

>
>
> On Tue, Mar 17, 2015 at 3:29 PM Zaur Shibzukhov <szport at gmail.com> wrote:
>
>> Yes... But I expected that dict constructor will use `__getitem__`  or
>> `items` method of MyDict instance  in order to retrieve items of the MyDict
>> instance during construction of the dict instance... Instead it interpreted
>> MyDict instance as the dict instance during construction of new dict.This
>> exactly caused my confusion.
>>
>
> It's because you subclassed dict. Copying is optimized to skip over using
> the methods you listed when the object is a dict and so we know the
> structure of the object at the C level. You can look at
> https://hg.python.org/cpython/file/22a0c925a7c2/Objects/dictobject.c#l1997
> to see the actual code.
>
> -Brett
>
>
>>
>> ---
>> *Zaur Shibzukhov*
>>
>>
>> 2015-03-17 22:12 GMT+03:00 Brett Cannon <brett at python.org>:
>>
>>>
>>>
>>> On Tue, Mar 17, 2015 at 3:05 PM Zaur Shibzukhov <szport at gmail.com>
>>> wrote:
>>>
>>>> Hello!
>>>>
>>>> In order to explain, let define subclass of dict:
>>>>
>>>> class Pair:
>>>>     def __init__(self, key, val):
>>>>         self.key = key
>>>>         self.val = val
>>>>
>>>> class MyDict(dict):
>>>>     #
>>>>     def __init__(self, *args, **kwds):
>>>>         if len(args) > 1:
>>>>             raise TypeError('Expected at most 1 arguments, but got %d'
>>>> % len(args))
>>>>
>>>>         for key, val in args[0]:
>>>>             self[key] = val
>>>>
>>>>         for key, val in kwds.items():
>>>>             self[key] = val
>>>>
>>>>     def __getitem__(self, key):
>>>>         pair = dict.__getitem__(key)
>>>>         return pair.value
>>>>
>>>>     def __setitem__(self, key, val):
>>>>         if key in self:
>>>>             pair = dict.__getitem__(key)
>>>>             pair.value = value
>>>>         else:
>>>>             pair = Pair(key, val)
>>>>             dict.__setitem__(self, key, pair)
>>>>
>>>>     def values(self):
>>>>         for key in self:
>>>>             p = dict.__getitem__(self, key)
>>>>             yield p.value
>>>>
>>>>     def items(self):
>>>>         for key, p in dict.__iter__(self):
>>>>             yield p.key, p.value
>>>>
>>>>
>>>> The simple test give me strange result:
>>>>
>>>> >>> d = MyDict([('a', 1), ('b', 2), ('c', 3)])
>>>> >>> dict(d)
>>>> {'a': <__main__.Pair at 0x104ca9e48>,
>>>>  'b': <__main__.Pair at 0x104ca9e80>,
>>>>  'c': <__main__.Pair at 0x104ca9eb8>}
>>>>
>>>> instead of {'a':1, 'b':2, 'c':3}.
>>>>
>>>>
>>>> Is this right behavior of the dict?
>>>>
>>>
>>> Yes because in your __setitem__ call you are storing the value as the
>>> Pair. So when dict prints its repr it prints the key and value, and in this
>>> case the value is a Pair.
>>>
>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20150317/25bbd4da/attachment.html>


More information about the Python-Dev mailing list