python如何实现不可变字典inmutabledict


Posted in Python onJanuary 08, 2020

这篇文章主要介绍了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 相关文章推荐
Python中用Descriptor实现类级属性(Property)详解
Sep 18 Python
用Python实现协同过滤的教程
Apr 08 Python
Python下的twisted框架入门指引
Apr 15 Python
安装dbus-python的简要教程
May 05 Python
利用Python如何批量更新服务器文件
Jul 29 Python
在Python中通过getattr获取对象引用的方法
Jan 21 Python
Python基于plotly模块实现的画图操作示例
Jan 23 Python
Python中BeautifuSoup库的用法使用详解
Nov 15 Python
Python实现自动签到脚本的示例代码
Aug 19 Python
python爬虫 requests-html的使用
Nov 30 Python
Python基于mediainfo批量重命名图片文件
Dec 29 Python
Python天气语音播报小助手
Sep 25 Python
PyQt5 closeEvent关闭事件退出提示框原理解析
Jan 08 #Python
python从内存地址上加载python对象过程详解
Jan 08 #Python
PyCharm第一次安装及使用教程
Jan 08 #Python
Python namedtuple命名元组实现过程解析
Jan 08 #Python
Pytorch基本变量类型FloatTensor与Variable用法
Jan 08 #Python
python pycharm最新版本激活码(永久有效)附python安装教程
Sep 18 #Python
pytorch 中pad函数toch.nn.functional.pad()的用法
Jan 08 #Python
You might like
php实现ip白名单黑名单功能
2015/03/12 PHP
Symfony生成二维码的方法
2016/02/04 PHP
php+Ajax无刷新验证用户名操作实例详解
2019/03/04 PHP
jQuery.each()用法分享
2012/07/31 Javascript
获取中文字符串的实际长度代码
2014/06/05 Javascript
javascript实现修改微信分享的标题内容等
2014/12/11 Javascript
jquery处理页面弹出层查询数据等待操作实例
2015/03/25 Javascript
javascript搜索框效果实现方法
2015/05/14 Javascript
jQuery点击输入框显示验证码图片
2016/05/19 Javascript
基于JQuery实现图片上传预览与删除操作
2016/05/24 Javascript
js oncontextmenu事件使用详解
2017/03/25 Javascript
基于VUE选择上传图片并页面显示(图片可删除)
2017/05/25 Javascript
webpack 2.x配置reactjs基本开发环境详解
2017/08/08 Javascript
vue跨域解决方法
2017/10/15 Javascript
nodejs初始化init的示例代码
2018/10/10 NodeJs
vue点击标签切换选中及互相排斥操作
2020/07/17 Javascript
使用vant的地域控件追加全部选项
2020/11/03 Javascript
nuxt.js服务端渲染中axios和proxy代理的配置操作
2020/11/06 Javascript
python中numpy的矩阵、多维数组的用法
2018/02/05 Python
使用python生成目录树
2018/03/29 Python
Python实现爬虫从网络上下载文档的实例代码
2018/06/13 Python
python常用函数与用法示例
2019/07/02 Python
解决Djang2.0.1中的reverse导入失败的问题
2019/08/16 Python
Django xadmin开启搜索功能的实现
2019/11/15 Python
在python中使用pymysql往mysql数据库中插入(insert)数据实例
2020/03/02 Python
基于Numba提高python运行效率过程解析
2020/03/02 Python
keras模型保存为tensorflow的二进制模型方式
2020/05/25 Python
使用Numpy对特征中的异常值进行替换及条件替换方式
2020/06/08 Python
Python之字典对象的几种创建方法
2020/09/30 Python
巴黎卡诗美国官方网站:始于1964年的头发头皮护理专家
2017/07/10 全球购物
巴西化妆品商店:Lojas Rede
2019/07/26 全球购物
为您搜罗全球潮流時尚品牌:HBX
2019/12/04 全球购物
高中生的自我评价
2014/03/04 职场文书
公开承诺书格式
2014/05/21 职场文书
司法局火灾防控方案
2014/06/05 职场文书
2016小学教师读书心得体会
2016/01/13 职场文书