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装饰器decorator介绍
Nov 21 Python
在Python中使用mechanize模块模拟浏览器功能
May 05 Python
python读取TXT到数组及列表去重后按原来顺序排序的方法
Jun 26 Python
python插入排序算法实例分析
Jul 03 Python
Python爬虫DNS解析缓存方法实例分析
Jun 02 Python
对TensorFlow中的variables_to_restore函数详解
Jul 30 Python
python 直接赋值和copy的区别详解
Aug 07 Python
基于Django框架的权限组件rbac实例讲解
Aug 31 Python
Python OpenCV视频截取并保存实现代码
Nov 30 Python
Python requests模块安装及使用教程图解
Jun 30 Python
python实现canny边缘检测
Sep 14 Python
彻底解决pip下载pytorch慢的问题方法
Mar 01 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
全国中波电台频率表
2020/03/11 无线电
PHP 采集程序原理分析篇
2010/03/05 PHP
php实现最简单的MVC框架实例教程
2014/09/08 PHP
php保存信息到当前Session的方法
2015/03/16 PHP
Laravel搭建后台登录系统步骤详解
2016/07/26 PHP
PHP简单装饰器模式实现与用法示例
2017/06/22 PHP
Thinkphp 5.0实现微信企业付款到零钱
2018/09/30 PHP
JavaScript 组件之旅(四):测试 JavaScript 组件
2009/10/28 Javascript
Tinymce+jQuery.Validation使用产生的BUG
2010/03/29 Javascript
JS控件的生命周期介绍
2012/10/22 Javascript
JS中typeof与instanceof之间的区别总结
2013/11/14 Javascript
jquery设置按钮停顿3秒不可用
2014/03/07 Javascript
jQuery中toggleClass()方法用法实例
2015/01/05 Javascript
JavaScript高级程序设计(第三版)学习笔记6、7章
2016/03/11 Javascript
Wireshark基本介绍和学习TCP三次握手
2016/08/15 Javascript
AngularJs Forms详解及简单示例
2016/09/01 Javascript
作为老司机使用 React 总结的 11 个经验教训
2017/04/08 Javascript
vue.js框架实现表单排序和分页效果
2017/08/09 Javascript
vue主动刷新页面及列表数据删除后的刷新实例
2018/09/16 Javascript
node.js express捕获全局异常的三种方法实例分析
2019/12/27 Javascript
vue项目打包后提交到git上为什么没有dist这个文件的解决方法
2020/09/16 Javascript
[02:54]DOTA2英雄基础教程 撼地者
2014/01/14 DOTA
使用python的chardet库获得文件编码并修改编码
2014/01/22 Python
python实现socket端口重定向示例
2014/02/10 Python
Python编程快速上手——Excel表格创建乘法表案例分析
2020/02/28 Python
日本钓鱼渔具和户外用品网上商店:naturum
2016/08/07 全球购物
朗仕(Lab series)英国官网:雅诗兰黛集团男士专属护肤品牌
2017/11/28 全球购物
英国儿童设计师服装和玩具购物网站:Zac & Lulu
2020/10/19 全球购物
中专药剂专业应届毕的自我评价
2013/12/27 职场文书
2015年文员个人工作总结
2015/04/09 职场文书
幼儿园教学工作总结2015
2015/05/12 职场文书
撤诉状格式范本
2015/05/19 职场文书
从事会计工作年限证明
2015/06/23 职场文书
工作态度怎么写
2015/06/25 职场文书
大学生暑假实习总结
2015/07/13 职场文书
python神经网络ResNet50模型
2022/05/06 Python