On Tue, Mar 17, 2015 at 3:46 PM Zaur Shibzukhov <szp...@gmail.com> wrote:
> So in such cases it should not subclassed `dict`, but > `collections.MutableMapping`, for example? > Yes (see the comment at https://hg.python.org/cpython/file/22a0c925a7c2/Objects/dictobject.c#l2003 ). -Brett > > --- > *Zaur Shibzukhov* > > > 2015-03-17 22:38 GMT+03:00 Brett Cannon <br...@python.org>: > >> >> >> On Tue, Mar 17, 2015 at 3:29 PM Zaur Shibzukhov <szp...@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 <br...@python.org>: >>> >>>> >>>> >>>> On Tue, Mar 17, 2015 at 3:05 PM Zaur Shibzukhov <szp...@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. >>>> >>> >>> >
_______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com