如果用户在字典中输入重复键,我会尝试引发错误。字典在文件中,用户可以手动编辑文件。
示例:
dico= {'root':{
'a':{'some_key':'value',...},
'b':{'some_key':'value',...},
'c':{'some_key':'value',...},
...
'a':{'some_key':'value',...},
}
}
新密钥'a'已经存在......
当我从文件加载dico时,如何测试dico并警告用户?
答案 0 :(得分:15)
编写dict的子类,覆盖__setitem__,以便在替换现有密钥时抛出错误;重写文件以使用新的子类的构造函数而不是默认的dict内置函数。
import collections
class Dict(dict):
def __init__(self, inp=None):
if isinstance(inp,dict):
super(Dict,self).__init__(inp)
else:
super(Dict,self).__init__()
if isinstance(inp, (collections.Mapping, collections.Iterable)):
si = self.__setitem__
for k,v in inp:
si(k,v)
def __setitem__(self, k, v):
try:
self.__getitem__(k)
raise ValueError("duplicate key '{0}' found".format(k))
except KeyError:
super(Dict,self).__setitem__(k,v)
然后你的文件必须写成
dico = Dict(
('root', Dict(
('a', Dict(
('some_key', 'value'),
('another_key', 'another_value')
),
('b', Dict(
('some_key', 'value')
),
('c', Dict(
('some_key', 'value'),
('another_key', 'another_value')
),
....
)
)
使用元组而不是dicts进行文件导入(使用{}表示法编写,它将使用默认的dict构造函数,并且重复项将在Dict构造函数获取它们之前消失!)。
答案 1 :(得分:4)
如果密钥已经存在,您将需要具有可以拒绝ValueError的自定义dict。
class RejectingDict(dict):
def __setitem__(self, k, v):
if k in self.keys():
raise ValueError("Key is already present")
else:
return super(RejectingDict, self).__setitem__(k, v)
以下是它的工作原理。
>>> obj = RejectingDict()
>>> obj[1] = True
>>> obj[2] = False
>>> obj
{1: True, 2: False}
>>> obj[1] = False
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "rejectingdict.py", line 4, in __setitem__
raise ValueError("Key is already present")
ValueError: Key is already present
答案 2 :(得分:2)
错误的方式 回去
from x import dico
不是一个好主意 - 你让USERS编辑代码,然后盲目执行。你冒着简单拼写错误的风险导致语法错误,直到像import os; os.system("rm whatever"); dico = {}
这样的恶意内容。
不要对子类dict
表示不满意。编写自己的dict-of-dicts加载程序。这并不难...读取数据文件,在每次插入之前检查密钥是否已经存在;如果是,请使用有意义的内容(如行号和重复键及其值)记录错误消息。最后,如果有任何错误,请提出异常。您可能会发现现有模块可以完成所有这些...... Python提供的ConfigParser aka configparser似乎不是您想要的。
顺便说一下,顶层没有一个“root”键而没有意义吗?
答案 3 :(得分:1)
Python的默认行为是在声明字典时静默覆盖重复项。
您可以创建自己的字典类,在添加新元素之前检查项目是否已经在字典中,然后使用它。但是,您必须将该文件中dico
的声明更改为允许重复的内容,例如元组列表。
然后在加载该数据文件时,您将其解析为特殊的“子类”字典。
答案 4 :(得分:1)
如果您想确保在使用重复键的dict
构造期间引发错误,只需利用Python的本机关键字参数检查:
> dict(a={}, a={})
SyntaxError: keyword argument repeated
除非我遗漏了某些内容,否则无需继承dict
。