如何在扩展dict时正确覆盖方法键()(在python3中)

时间:2015-11-09 15:31:14

标签: python python-3.x dictionary key extending

编辑:我添加了课程和一些信息,请参阅新帖子。

我创建了一个扩展dictset的类(更确切地说,我扩展了collections.abc.MutableMappingMutableSet)。现在我想正确覆盖方法keys()

此类表示一组名为Measurand的其他对象:

class Measurands(MutableSet, MutableMapping):
    @property
    def measurands(self):
        return self._measurands


    @measurands.setter
    def measurands(self, val):
        self._measurands = []

        for el in val:
            self.add(el)


    def __init__(self, arg=None):
        if arg is None:
            self.measurands = []
        else:
            try:
                measurands = arg.measurands
            except AttributeError:
                if isinstance(arg, Iterable):
                    measurands = list(arg)
                else:
                    measurands = [arg]

            self.measurands = measurands


    def __iter__(self):
        return iter(self.measurands)


    def __getitem__(self, key):
        for m in self:
            if m.id == key:
                return m

        raise KeyError(key)


    def __contains__(self, el_x):
        is_in = False

        for el in self:
            if el_x.id == el.id:
                is_in = True
                break

        return is_in


    def add(self, el):
        try:
            self[el.id].session_ids |= el.session_ids
        except KeyError:
            self[el.id] = Measurand(el)


    def _discard(self, key):
        res = False

        for i, m in enumerate(self):
            if m.id == key:
                del self.measurands[i]
                res = True
                break

        return res


    def __delitem__(self, key):
        res = self._discard(self, key)

        if not res:
            raise KeyError(key)

    def discard(self, key):
        self._discard(self, key)


    def remove(self, key):
        self.__delitem__(self, key)


    def __len__(self):
        return len(self.measurands)


    def __setitem__(self, key, value):
        res = False
        value_true = Measurand(value)

        for i, m in enumerate(self):
            if m.id == key:
                res = True

                if value.id == key:
                    self.measurands[i] = value_true
                else:
                    raise KeyError(key)

                break

        if not res:
            self.measurands.append(value_true)


    def __str__(self):
        string = "Measurands({"

        for m in self:
            string += str(m)
            string += ", "

        if string:
            string = string[:-2]

        string += "})"

        return string

问题是默认方法keys返回"列表" Measurand个对象。这不是我想要的。键应该是id对象的属性Measurand

现在我返回一个简单的list,但我会返回dict_keyscollection.abc.KeysView个对象。不幸的是,dict_keys不是全局名称。

  1. dict_keys在哪里?
  2. 这是正确的/ pythonic方式吗?

3 个答案:

答案 0 :(得分:0)

我还没有找到任何方法将某些内容转换为dict_keys类型,但在阅读了介绍访问键和值(PEP 3106)的新方法的PEP之后,看起来dict_keys被引入了

  

返回一个类似于集合或无序的容器对象,其内容是从基础字典派生的,而不是作为密钥副本的列表等。

考虑到这一点,看起来您可以使用keys()方法而不是列表返回生成器对象。

以下是PEP的伪代码:

class dict:

    # Omitting all other dict methods for brevity.

    def keys(self):
        return d_keys(self)

class d_keys:

    def __init__(self, d):
        self.__d = d

    def __len__(self):
        return len(self.__d)

    def __contains__(self, key):
        return key in self.__d

    def __iter__(self):
        for key in self.__d:
            yield key

答案 1 :(得分:0)

Python3文档说dict.keys()返回值类型(即视图)是"类似于",所以你的返回值应该是" set-like"同样。

  

dict.keys(),dict.values()和dict.items()返回的对象   是视图对象。它们提供了字典的动态视图   条目,表示当字典更改时,视图   反映了这些变化。

     

可以迭代字典视图以产生它们   各自的数据和支持会员资格测试:

     

...

     

键视图设置类似,因为它们的条目是唯一且可清除的。   如果所有值都是可清除的,那么(键,值)对是唯一的   hashable,那么items视图也是类似的。 (值视图不是   由于条目通常不是唯一的,因此被视为类似集合。)对于   类似于集合的视图,为抽象基础定义的所有操作   class collections.abc.Set可用(例如,==,<,或^)。

全文: https://docs.python.org/3/library/stdtypes.html#dict-views

答案 2 :(得分:0)

这已经为您处理了! collections.abc.MutableMapping包含keys的合理默认实施,提供与dict.keys相同的界面。

只需删除您的keys方法,即可使用继承的实现。