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

Tha*_*mas 11 python dictionary duplicates

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

例:

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

                'a':{'some_key':'value',...},
              }
      }
Run Code Online (Sandbox Code Playgroud)

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

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

Hug*_*ell 16

编写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)
Run Code Online (Sandbox Code Playgroud)

然后你的文件必须写成

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')
        ),

        ....
    )
)
Run Code Online (Sandbox Code Playgroud)

使用元组而不是dicts进行文件导入(使用{}表示法编写,它将使用默认的dict构造函数,并且重复项将在Dict构造函数获取它们之前消失!).


Jia*_*ian 6

如果您想确保在dict使用重复键进行构造期间引发错误,只需利用 Python 的本机关键字参数检查:

> dict(a={}, a={})
SyntaxError: keyword argument repeated
Run Code Online (Sandbox Code Playgroud)

除非我遗漏了什么,否则不需要子类化dict

  • 关于这个答案,重要的是要注意一些事情:(1)它禁止在*构造*时重复键,但允许之后覆盖键(即“d['a'] = 'new_value'”是可以的);(2) 它要求所有键都是字符串,而子类化允许使用其他类型的键,例如“元组”。尽管如此,这也是我的方法,而且它似乎最符合OP的要求。 (3认同)
  • 为什么这不是公认的答案?这是处理这个问题的超级 Pythonic 方式。 (2认同)
  • 如果键可能不是字符串,这也不起作用: `dict(1="foo")` 和 `dict(None="foo")` 会引发异常,但 `{None: "foo"}` 和 ` {1: "foo"}` 工作。 (2认同)