如何在Python中强制字典拒绝更新现有键?

10

在Python中,是否有可能设计一个字典,如果错误地添加了一个已经存在于字典中的键,则该键会被拒绝?

谢谢。

2
我想指出,“唯一键”是字典的固有属性。当您插入一个键/值对时,它会更新任何导致重复键的先前条目。因此,您的问题让我感到困惑。现在,当我仔细阅读这个问题时,我理解您所要求的是防止这种更新-这是一个有效且可以理解的扩展。我只是想澄清这一点,以便其他读者不会被误导认为他们需要在更广泛的意义上防止重复键。 - BuvinJ
正如我们在下面user2197172的答案中所看到的那样,使用“setdefault”是一种补充方式:它会悄悄地吞噬尝试添加重复键的操作。 - Tom Hundt
我提交了问题的编辑以准确反映用户真正想问的内容。现在它听起来像一个有用的问题(如何更改Python的默认行为?),而不是完全多余的问题(如何让Python执行它已经强制执行的操作?)。 - Tripartio
4个回答

23

你可以随时创建自己的字典。

class UniqueDict(dict):
    def __setitem__(self, key, value):
        if key not in self:
            dict.__setitem__(self, key, value)
        else:
            raise KeyError("Key already exists")

10
请注意,当__init__方法仅用相同的参数调用父级__init__方法时,实际上并不需要该方法。 - Lauritz V. Thaulow
我认为这是正确的答案,但我不太喜欢这个类的名称。请看我在最初问题上的评论。也许像“InsertOnlyDict”或“NoUpdateDict”之类的名称会更清晰明了? - BuvinJ
1
随便叫什么都可以。真的没关系。不,我不会编辑这个答案。 - Jakob Bowyer
如果键已经存在,是否可以添加值。就像这样的 else 语句: dict.setitem(self, key, self.value + value)。我尝试过这样做,但它只是更新了值。 - Manvi
3
当重复的键被传递给构造函数时,这仍然会吞噬它们,例如UniqueDict([('a',1),('a',1)])返回{'a':1}。 - bzu

5

在添加项目之前,请检查您的字典

if 'k' not in mydict:
    mydict.update(myitem)

你可以直接使用:if 'k' not in mydict,不需要加上 .keys() :) - mouad
1
@singularity:你应该(不是可以)避免使用.keys()...这是一种极大的资源浪费。 - John Machin
抱歉,那是一个疏忽。在答案中已经修复了。 - Gevious

2
这是 setdefault 的目的:
>>> x = {}
>>> print x.setdefault.__doc__
D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D
>>> x.setdefault('a', 5)
5
>>> x
{'a': 5}
>>> x.setdefault('a', 10)
5
>>> x
{'a': 5}

这也意味着你可以跳过"if 'key' in dict: ... else: ..."这样的语句。
>>> for val in range(10):
...     x.setdefault('total', 0)
...     x['total']+=val
...
0
0
1
3
6
10
15
21
28
36
>>> x
{'a': 5, 'total': 45}

这是一个可爱的答案,实际上重复的键被悄悄地吞噬了——但这是否意味着被“拒绝”了呢?没有引发任何异常。 - Tom Hundt
你指出“rejected”要求是正确的,如果这意味着抛出异常,那么它会失败。我的假设是,“rejected”是相对于字典中值的更新而言的,而不是用于指示错误处理。 - user2197172

0

您可以通过从 dict 派生并覆盖 __setitem__ 来拒绝已经存在于字典中的项从而创建自定义字典。


1
@Hossein:@Jakob的回答提供了一个例子。 - Björn Pollex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接