python如何实现不可变字典inmutabledict
这篇文章主要介绍了python如何实现不可变字典inmutabledict,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
关于在python中如何实现不可变字典的方法。早在pep416中,就建议python官方实现inmutabledict,但是官方否认了。理由主要是
- 根据RaymondHettinger的说法,使用frozendict很愚蠢。那些使用它的人倾向于仅将它用作提示,例如声明全局或类级别的“常量”:它们实际上不是永久不变的,因为任何人仍然可以指定名称。
- Thereareexistingidiomsforavoidingmutabledefaultvalues.
所以,这个提议就被否决了。但是我们依旧可以自己实现一个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。不就是可以达到无法修改字典的值的目的了嘛。代码如下
classmyDict(dict): def__setitem__(self,key,value): raiseTypeError("inmutabledictcannotbemodifyedvalue") d=myDict({1:2,3:4}) d[1]=4
运行则会提示
raiseTypeError("inmutabledictcannotbemodifyedvalue") TypeError:inmutabledictcannotbemodifyedvalue Processfinishedwithexitcode1
很好,完美的完成了任务。这种方法应用最为广泛,在werkzeug框架中的ImmutableDict等,就是通过修改魔术方法来实现的不可变字典类型。
但是在pep0416中,还提到了几种其他方法,PyDictProxy_New等。下面来试一下
2.pythonapi.PyDictProxy_New
在官方介绍capi的PyDictProxy_New中,使用代理模式,代理使用字典。并且拦截了字典的修改请求。介绍如下
PyObject*PyDictProxy_New(PyObject*mapping)¶ Returnvalue:Newreference. Returnatypes.MappingProxyTypeobjectforamappingwhichenforcesread-onlybehavior.Thisisnormallyusedtocreateaviewtopreventmodificationofthedictionaryfornon-dynamicclasstypes.
意思就是你传入个dict,这个函数返回一个dict(其实是types.MappingProxyType),然后这个返回的dict就不可以修改啦。是不是很简单,代码实现如下
#!/usr/bin/envpython #-*-coding:UTF-8-*- fromctypesimportpythonapi,py_object PyDictProxy_New=pythonapi.PyDictProxy_New PyDictProxy_New.argtypes=(py_object,) PyDictProxy_New.restype=py_object defmake_dictproxy(obj): assertisinstance(obj,dict) returnpythonapi.PyDictProxy_New(obj) a={'a':'b','c':'d'} d=make_dictproxy(a)
这是如果修改的话,则会提示TypeError:'mappingproxy'objectdoesnotsupportitemassignment。同样达到了要求。这种方法的弊端主要在于依赖特定的平台,只能适用于cpython。而上面那种则适用于所有平台,cpython,pypy等。
3.classtypes.MappingProxyType(mapping)
这种方法其实于PyDictProxy_New一样,只不过在py3.3中才实现。
代码如下
fromtypesimportMappingProxyType defmake_dictproxy(obj): assertisinstance(obj,dict) returnMappingProxyType(obj)
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。