python 不可变的字典类

作者: AlexSun1995 | 来源:发表于2017-12-20 22:51 被阅读95次

问题

实验楼python挑战赛1 实现一个不可变的dict,数据只能由类初始化的时候通过参数传递,修改、添加都会抛出TypeError

解决方法

继承ABCs中的MultiMapping, 复写其中的部分方法即可。

代码

import collections


class ImmutableDict(collections.MutableMapping):
 def __init__(self, **kwargs):
     self.store = dict(**kwargs)
     self.error = TypeError("'ImmutableDict' objects are immutable")
     # self.update(dict(*args, **kwargs))

 def __setitem__(self, key, value):
     # 涉及到修改时会触发这个方法
     raise self.error

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

 def __delitem__(self, key):
     # 删除时触发
     raise self.error

 def __getitem__(self, key):
     return self.store[key]

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


class Get(object):
 def __init__(self):
     pass

 def __getitem__(self, item):
     return hash(item)


if __name__ == "__main__":
 test = ImmutableDict(name="sun", age=22, location="China")
 # test["name"] = "zhang"
 # test.pop("name")   TypeError will raised..
 # print(test.pop("name"))
 # for item in test:
     # print(item)
     #print(test[item])

MultiMapping 源码:

class MutableMapping(Mapping):

    @abstractmethod
    def __setitem__(self, key, value):
        raise KeyError

    @abstractmethod
    def __delitem__(self, key):
        raise KeyError

    __marker = object()

    def pop(self, key, default=__marker):
        try:
            value = self[key]
        except KeyError:
            if default is self.__marker:
                raise
            return default
        else:
            del self[key]
            return value

    def popitem(self):
        try:
            key = next(iter(self))
        except StopIteration:
            raise KeyError
        value = self[key]
        del self[key]
        return key, value

    def clear(self):
        try:
            while True:
                self.popitem()
        except KeyError:
            pass

    def update(self, other=(), **kwds):
        if isinstance(other, Mapping):
            for key in other:
                self[key] = other[key]
        elif hasattr(other, "keys"):
            for key in other.keys():
                self[key] = other[key]
        else:
            for key, value in other:
                self[key] = value
        for key, value in kwds.items():
            self[key] = value

    def setdefault(self, key, default=None):
        try:
            return self[key]
        except KeyError:
            self[key] = default
        return default

MutableMapping.register(dict)

Mapping 源码:

class Mapping(Sized, Iterable, Container):

    @abstractmethod
    def __getitem__(self, key):
        raise KeyError

    def get(self, key, default=None):
        try:
            return self[key]
        except KeyError:
            return default

    def __contains__(self, key):
        try:
            self[key]
        except KeyError:
            return False
        else:
            return True

    def iterkeys(self):
        return iter(self)

    def itervalues(self):
        for key in self:
            yield self[key]

    def iteritems(self):
        for key in self:
            yield (key, self[key])

    def keys(self):
        return list(self)

    def items(self):
        return [(key, self[key]) for key in self]

    def values(self):
        return [self[key] for key in self]

    # Mappings are not hashable by default, but subclasses can change this
    __hash__ = None

    def __eq__(self, other):
        if not isinstance(other, Mapping):
            return NotImplemented
        return dict(self.items()) == dict(other.items())

    def __ne__(self, other):
        return not (self == other)

分析两个问题:

  • .get 的时候究竟发生了什么?
  • .pop 的时候发生了什么?

尝试进行断点调试:

尝试

get 跳转到了Mapping中的get

image.png
image.png

注意其中的self就是我们实例化的immutableDict类

结论: .get显示定义是在Mapping中,但是Mapping又把这个方法的实现抛给了子类,事实上,就是调用了 immutableDict.getitem中的方法。
所以我们在get 会触发我们在 immutableDict.getitem中定义的异常
pop 也就很类似了。

相关文章

  • day 8集合、函数基操

    1.字典(dict) 1.什么是字典(dict) 字典是python内置的容器类的数据类型,可变,无序的。****...

  • python 不可变的字典类

    问题 实验楼python挑战赛1 实现一个不可变的dict,数据只能由类初始化的时候通过参数传递,修改、添加都会抛...

  • Day8-2 字典

    二、字典 字典基础 什么是字典(dict)python提供的容器型数据类型,可变并且无序可变 - 支持元素的增删改...

  • Python可变类型与不可变类型

    Python可变类型与不可变类型 1、可变类型:List(列表),Dic(字典),Set(集合) 2、不可变类型:...

  • 列表

    Python中的数据类型:数字(不可变)、字符串(不可变)、列表(可变)、元祖(不可变)、字典(可变)、集合 容器...

  • 2018年6月19日【python学习笔记】

    列表 python中的数据类型:数字(不可变)、字符串(不可变)、列表(可变)、元祖(不可变)、字典(可变)、集合...

  • 使用Runtime防止数组、字典越界

    获取数组class 核心方法 可变数组、字典、可变字典的崩溃问题等(思路和数组一致,获取类名的方法及对应的方法名不...

  • Python中 可变、不可变数据类型和hash

    一、可变和不可变数据类型 在python中,我们对数据类型除了分为数字类型、字符串类型、列表类型、元组类型、字典类...

  • Python dict字典

    4.13 Python dict字典 Python 字典(dict)是一种无序的、可变的序列,它的元素以 键值对(...

  • python字典与集合

    字典 python中的字典是一种可变、无序的容器类型,可变即字典中的元素增删改,无序即不能根据下标(索引)来获取其...

网友评论

    本文标题:python 不可变的字典类

    本文链接:https://www.haomeiwen.com/subject/pbonwxtx.html