Python 有办法限制字典不能添加新键吗 ?

2020-02-08 13:46:15 +08:00
 black11black

如题,在自己开发 library

目前希望做到的一个效果是,比如

class configure:
	def __init__(self):
		param1_set = {'person_number':12}
        param2_set = {'age': 1}

如果我生成一个 configure 对象用来对库的行为进行控制,我不希望用户可以随意修改其中的数值,我希望将可修改的范围完全限制在我初始化规定的范围里。

众所周知用__slots__可以限制属性不能超出范围 但是像我这样属性内部放的是字典对象,字典的键值对还是可以随意修改的,可能导致各种未知问题 有什么解决办法吗?

3947 次点击
所在节点    Python
20 条回复
Livid
2020-02-08 13:51:18 +08:00
这里有一些实现可以参考:

https://www.python.org/dev/peps/pep-0416/
monsterxx03
2020-02-08 14:02:41 +08:00
写个 class 继承 dict,重载__setitem__,直接抛异常
ipwx
2020-02-08 14:04:30 +08:00
dataclass frozen=true?
freakxx
2020-02-08 14:07:29 +08:00
可以考虑写个

继承 dict, 复写 __setitem__
freakxx
2020-02-08 14:08:33 +08:00
https://github.com/slezica/python-frozendict

也有这样的库,可以参考下实现
imn1
2020-02-08 14:09:39 +08:00
标题是键,正文是值,那么究竟修改 value 还是 key ?
value 的话,可以 forzendict,或者直接用 pickle 二进制保存
key 的话,可以预置一个固定 key 的 dict,然后从输入更新 value,舍弃非预置的 key
Leigg
2020-02-08 14:24:26 +08:00
多了解一下双下划线开头的方法
est
2020-02-08 14:33:07 +08:00
namedtuple 香~
ClericPy
2020-02-08 14:40:05 +08:00
0. https://www.dogedoge.com/results?q=Python+immutable+dict
1. 用户只要想改, 动态语言基本上用点成本都能改改
2. 主流的保护方式是双下划线保护基类, 子类改起来就很麻烦
3. 可以用一些 immutable 对象做属性调用, 比如基于数组的 namedtuple, 当然 frozendict 和 immutables 这俩库也可以, 就是有点多余了
4. 感觉有点杞人忧天过早优化了, 实在不行, 自己继承个 dict 在 __setitems__ 里面加上一个 warning 就够了
laike9m
2020-02-08 15:41:28 +08:00
@Livid 感觉 types.MappingProxyType 应该是正解了,虽然还是只能期待用户不会直接改包含在其中的 dict
laike9m
2020-02-08 15:44:32 +08:00
@Livid 感觉 types.MappingProxyType 应该是正解了,虽然还是只能期待用户不会直接改包含在其中的 dict
@monsterxx03 这个比你想的要 tricky: https://stackoverflow.com/q/2060972/2142577
frostming
2020-02-08 19:18:14 +08:00
@monsterxx03 直接继承 dict 不是个好方法,(tomlkit 就是这样,我都报过好几个 bug 了) https://treyhunner.com/2019/04/why-you-shouldnt-inherit-from-list-and-dict-in-python/

@laike9m 用 collections.abc.Mapping 可能比 types.MappingProxyType 要更好一点
aguesuka
2020-02-08 21:30:20 +08:00
不要暴露字典接口,而是自己提供一个方法比较好吧
black11black
2020-02-09 03:15:23 +08:00
@freakxx

试了一下 setitem 是无论新建键值对,还是修改已有条目都会调用的啊,不太满足需求
想看一下实现部分 py 的源码,这种不用库导入的 bif 找了半天没找到在什么地方。
laike9m
2020-02-09 03:47:31 +08:00
@frostming types.MappingProxyType 实际上就是 abc.Mapping,没什么区别的,还更方便
https://github.com/python/cpython/blob/3.8/Lib/_collections_abc.py#L691
freakxx
2020-02-09 15:30:04 +08:00
class FrozenDict(dict):
def __setitem__(self, key, value):
raise TypeError("'FrozenDict' object does not support item assignment")


frozen_dict = FrozenDict


你要的是这样?
freakxx
2020-02-09 15:33:43 +08:00
不过看了你发的这几个贴。。。实际上搞个 tuplename 就算了,
frostming
2020-02-09 20:10:55 +08:00
@laike9m 抽象类和具体类的区别
RRRoger
2020-02-10 09:55:29 +08:00
frozen dict
cassidyhere
2020-02-10 10:16:29 +08:00
可以参考 werkzeug.datastructures 里实现的 ImmutableDict
flask 就用到了
class Flask(_PackageBoundObject):
...
default_config = ImmutableDict({"ENV": None, ...})

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/642967

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX