美文网首页我爱编程
python 不可变字典 inmutabledict的实现

python 不可变字典 inmutabledict的实现

作者: 烤土豆啦 | 来源:发表于2018-07-26 11:22 被阅读0次

python inmutabledict的实现

关于在python中如何实现不可变字典的方法。早在pep416中,就建议python官方实现inmutabledict,但是官方否认了。理由主要是

  • 根据Raymond Hettinger的说法,使用frozendict很愚蠢。 那些使用它的人倾向于仅将它用作提示,例如声明全局或类级别的“常量”:它们实际上不是永久不变的,因为任何人仍然可以指定名称。
  • There are existing idioms for avoiding mutable default values.

所以,这个提议就被否决了。但是我们依旧可以自己实现一个inmutabledict。inmutable主要的特点是

  • dict内的值只能在初始化的时候指定
  • 在运行期间,不能添加删除新增dict内部的值

结合starkoverflow上面的回答
我们可以通过如下几种魔改的方式实现python的inmutabledict

几种变通的方案

1. 最原始的方法,修改setitem魔术方法

在python中,d["foo"]=bar,将foo和bar作为参数,调用的是python的模式方法__setitem__。函数原型为def __setitem__(self, key, value):。所以,我们可以继承dict类,实现自己的__setitem__。在修改值的时候,抛出TypeError。不就是可以达到无法修改字典的值的目的了嘛。代码如下

class myDict(dict):
    def __setitem__(self, key, value):
        raise TypeError("inmutabledict can not be modifyed value")

d = myDict({1:2,3:4})
d[1]=4

运行则会提示

    raise TypeError("inmutabledict can not be modifyed value")
TypeError: inmutabledict can not be modifyed value

Process finished with exit code 1

很好,完美的完成了任务。这种方法应用最为广泛,在werkzeug框架中的ImmutableDict等,就是通过修改魔术方法来实现的不可变字典类型。

但是在pep0416中,还提到了几种其他方法,PyDictProxy_New等。下面来试一下

2. pythonapi.PyDictProxy_New

在官方介绍capi的PyDictProxy_New中,使用代理模式,代理使用字典。并且拦截了字典的修改请求。介绍如下

PyObject* PyDictProxy_New(PyObject *mapping)¶
Return value: New reference.
Return a types.MappingProxyType object for a mapping which enforces read-only behavior. This is normally used to create a view to prevent modification of the dictionary for non-dynamic class types.

意思就是你传入个dict,这个函数返回一个dict(其实是types.MappingProxyType),然后这个返回的dict就不可以修改啦。是不是很简单,代码实现如下


#!/usr/bin/env python
# -*- coding: UTF-8 -*-


from ctypes import pythonapi, py_object

PyDictProxy_New = pythonapi.PyDictProxy_New
PyDictProxy_New.argtypes = (py_object,)
PyDictProxy_New.restype = py_object

def make_dictproxy(obj):
    assert isinstance(obj, dict)
    return pythonapi.PyDictProxy_New(obj)
a={'a': 'b', 'c': 'd'}
d = make_dictproxy(a)

这是如果修改的话,则会提示TypeError: 'mappingproxy' object does not support item assignment。同样达到了要求。这种方法的弊端主要在于依赖特定的平台,只能适用于cpython。而上面那种则适用于所有平台,cpython,pypy等。

3 .class types.MappingProxyType(mapping)

这种方法其实于PyDictProxy_New一样,只不过在py3.3中才实现。
代码如下

from types import  MappingProxyType

def make_dictproxy(obj):
    assert isinstance(obj, dict)
    return MappingProxyType(obj)

相关文章

  • python 不可变字典 inmutabledict的实现

    python inmutabledict的实现 关于在python中如何实现不可变字典的方法。早在pep416中,...

  • Day8-2 字典

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

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

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

  • 列表

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

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

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

  • Python dict字典

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

  • python字典与集合

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

  • 01.03 笔记-字典

    字典 什么是字典 python提供的容器型数据类型,可变并且无序的序列 可变 - 支持增删改 无序 - 不支持查,...

  • Python的可变对象与不可变对象 !

    在初学Python时,经常需要区分“可变对象”和“不可变对象”。其中,可变对象包括列表(list)、字典(dict...

  • Python都有哪些数据结构?

    Python自带的数据结构分为可变的和不可变的。可变的有:数组、集合、字典;不可变的有:字符串、元组、数。

网友评论

    本文标题:python 不可变字典 inmutabledict的实现

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