如果复制字典中的键,如何引发错误

时间:2011-02-15 01:54:30

标签: python dictionary duplicates

如果用户在字典中输入重复键,我会尝试引发错误。字典在文件中,用户可以手动编辑文件。

示例:

dico= {'root':{
                'a':{'some_key':'value',...},
                'b':{'some_key':'value',...},
                'c':{'some_key':'value',...},
                ...

                'a':{'some_key':'value',...},
              }
      }

新密钥'a'已经存在......

当我从文件加载dico时,如何测试dico并警告用户?

5 个答案:

答案 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