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类型强制转换long to int的代码
Feb 10 Python
python处理中文编码和判断编码示例
Feb 26 Python
Python实现PS滤镜中马赛克效果示例
Jan 20 Python
对python中array.sum(axis=?)的用法介绍
Jun 28 Python
PyTorch的深度学习入门之PyTorch安装和配置
Jun 27 Python
Python实现微信小程序支付功能
Jul 25 Python
Python CVXOPT模块安装及使用解析
Aug 01 Python
Python大数据之从网页上爬取数据的方法详解
Nov 16 Python
python面向对象之类属性和类方法案例分析
Dec 30 Python
tensorflow使用CNN分析mnist手写体数字数据集
Jun 17 Python
如何对python的字典进行排序
Jun 19 Python
Flask response响应的具体使用
Jul 15 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
单点登录 Ucenter示例分析
2013/10/29 PHP
php实现短信发送代码
2015/07/05 PHP
Zend Framework实现多服务器共享SESSION数据的方法
2016/03/22 PHP
浅谈PHP值mysql操作类
2016/06/29 PHP
总结PHP删除字符串最后一个字符的三种方法
2016/08/30 PHP
PJ Blog修改-禁止复制的代码和方法
2006/10/25 Javascript
JavaScript 参考教程
2006/12/29 Javascript
类似GMAIL的Ajax信息反馈显示
2010/02/16 Javascript
jquery加载页面的方法(页面加载完成就执行)
2011/06/21 Javascript
jquery.qrcode在线生成二维码使用示例
2013/08/21 Javascript
复制网页内容,粘贴之后自动加上网址的实现方法(脚本之家特别整理)
2014/10/16 Javascript
Javascript 获取鼠标当前的位置实现方法
2016/10/27 Javascript
nodejs中全局变量的实例解析
2017/03/07 NodeJs
vue中页面跳转拦截器的实现方法
2017/08/23 Javascript
vue通过点击事件读取音频文件的方法
2018/05/30 Javascript
浅析Vue 生命周期
2018/06/21 Javascript
Vue项目实现简单的权限控制管理功能
2019/07/17 Javascript
layui中select,radio设置不生效的解决方法
2019/09/05 Javascript
easyUI 实现的后台分页与前台显示功能示例
2020/06/01 Javascript
详解JavaScript类型判断的四种方法
2020/10/21 Javascript
[01:13]2015国际邀请赛线下观战现场
2015/08/08 DOTA
[04:13]2018国际邀请赛典藏宝瓶Ⅱ饰品一览
2018/07/21 DOTA
Ubuntu 下 vim 搭建python 环境 配置
2017/06/12 Python
详解Django之auth模块(用户认证)
2018/04/17 Python
python实现求两个字符串的最长公共子串方法
2018/07/20 Python
Python实现时间序列可视化的方法
2019/08/06 Python
查看Python依赖包及其版本号信息的方法
2019/08/13 Python
德国滑雪和户外用品网上商店:XSPO
2019/10/30 全球购物
HttpServlet类中的主要方法都有哪些?各自的作用是什么?
2014/03/16 面试题
统计岗位职责
2014/02/21 职场文书
文艺节目主持词
2015/07/06 职场文书
儿子满月酒致辞
2015/07/29 职场文书
2015年公司国庆放假通知
2015/07/30 职场文书
结婚纪念日感言
2015/08/01 职场文书
导游词之黄果树瀑布
2019/09/20 职场文书
python爬虫之爬取笔趣阁小说
2021/04/22 Python