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构造icmp echo请求和实现网络探测器功能代码分享
Jan 10 Python
Python序列操作之进阶篇
Dec 08 Python
浅谈Python中的bs4基础
Oct 21 Python
Python模块的加载讲解
Jan 15 Python
Python使用post及get方式提交数据的实例
Jan 24 Python
Python 一键获取百度网盘提取码的方法
Aug 01 Python
Pytorch之view及view_as使用详解
Dec 31 Python
使用Python实现牛顿法求极值
Feb 10 Python
Python模块/包/库安装的六种方法及区别
Feb 24 Python
pyqt5数据库使用详细教程(打包解决方案)
Mar 25 Python
django的autoreload机制实现
Jun 03 Python
python脚本定时发送邮件
Dec 22 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脚本数据库功能详解(上)
2006/10/09 PHP
PHP获取一年中每个星期的开始和结束日期的方法
2015/02/12 PHP
PHP简单日历实现方法
2016/07/20 PHP
PHP示例演示发送邮件给某个邮箱
2019/04/03 PHP
javascript基于jQuery的表格悬停变色/恢复,表格点击变色/恢复,点击行选Checkbox
2008/08/05 Javascript
使用隐藏的new来创建对象
2011/03/29 Javascript
JS this作用域以及GET传输值过长的问题解决方法
2013/08/06 Javascript
Flexigrid在IE下不显示数据的处理的解决方法
2013/10/24 Javascript
js调试系列 断点与动态调试[基础篇]
2014/06/18 Javascript
Javascript获取表单名称(name)的方法
2015/04/02 Javascript
Position属性之relative用法
2015/12/14 Javascript
快速解决jquery.touchSwipe左右滑动和垂直滚动条冲突
2016/04/15 Javascript
基于ajax与msmq技术的消息推送功能实现代码
2016/12/26 Javascript
vue多页面开发和打包正确处理方法
2018/04/20 Javascript
浅析js中mvvm模式实现的原理
2018/10/06 Javascript
node.js使用express框架进行文件上传详解
2019/03/03 Javascript
[03:56]还原FTP电影首映式 DOTA2群星拼出遗迹世界
2014/03/26 DOTA
[02:15]2014DOTA2国际邀请赛 专访LGD.lin小兔子是大腿
2014/07/14 DOTA
从零学python系列之浅谈pickle模块封装和拆封数据对象的方法
2014/05/23 Python
python里大整数相乘相关技巧指南
2014/09/12 Python
关于Python面向对象编程的知识点总结
2017/02/14 Python
Python获取当前公网ip并自动断开宽带连接实例代码
2018/01/12 Python
pandas删除行删除列增加行增加列的实现
2019/07/06 Python
django将数组传递给前台模板的方法
2019/08/06 Python
python speech模块的使用方法
2020/09/09 Python
英国天然宝石首饰购买网站:Gemondo Jewellery
2018/10/23 全球购物
.net开发工程师面试题
2014/02/25 面试题
在c#中using和new这两个关键字有什么意义
2013/05/19 面试题
个人收入证明范本
2014/01/12 职场文书
20年同学聚会邀请函
2014/02/04 职场文书
妈妈的账单教学反思
2014/02/06 职场文书
群众路线剖析材料范文
2014/10/09 职场文书
火烧圆明园的观后感
2015/06/03 职场文书
一百条裙子读书笔记
2015/07/01 职场文书
婚礼父母致辞
2015/07/28 职场文书
Python socket如何解析HTTP请求内容
2022/02/12 Python