如何通过d [key] = val来防止密钥创建

时间:2015-08-27 20:19:12

标签: python dictionary key python-3.4

假设我有d = {'dogs': 3}。使用:

d['cats'] = 2 

会创建密钥'cats'并为其赋值2

如果我真的打算用新的键和值更新dict,我会使用d.update(cats=2),因为它感觉更明确。

自动创建密钥会感觉容易出错(特别是在大型程序中),例如:

# I decide to make a change to my dict.
d = {'puppies': 4, 'big_dogs': 2}


# Lots and lots of code.
# ....

def change_my_dogs_to_maximum_room_capacity():
    # But I forgot to change this as well and there is no error to inform me.
    # Instead a bug was created.
    d['dogs'] = 1

问题:
有没有办法禁用自动创建通过d[key] = value不存在的密钥,而是提出KeyError

其他一切都应该继续工作:

d = new_dict()                  # Works
d = new_dict(hi=1)              # Works
d.update(c=5, x=2)              # Works
d.setdefault('9', 'something')  # Works

d['a_new_key'] = 1              # Raises KeyError

3 个答案:

答案 0 :(得分:5)

您可以使用特殊的dict方法创建__setitem__的子项,该方法拒绝在最初创建时不存在的键:

class StrictDict(dict):
    def __setitem__(self, key, value):
        if key not in self:
            raise KeyError("{} is not a legal key of this StricDict".format(repr(key)))
        dict.__setitem__(self, key, value)

x = StrictDict({'puppies': 4, 'big_dogs': 2})
x["puppies"] = 23 #this works
x["dogs"] = 42    #this raises an exception

它并非完全防弹(例如,它会允许x.update({"cats": 99})没有投诉),但它会阻止最可能的情况。

答案 1 :(得分:0)

继承__setitem__类并覆盖class mydict(dict): def __init__(self, *args, **kwargs): self.update(*args, **kwargs) def __setitem__(self, key, value): raise KeyError(key) >>>a=mydict({'a':3}) >>>d {'a': 3} >>>d['a'] 3 >>>d['b']=4 KeyError: 'b' 以满足您的需求。试试这个

class Program
{
    public virtual void CalculateArea(int a, int b)
    {
        Console.WriteLine(a * b);
    }
}
class progrmm1 : Program
{
    public override void CalculateArea(int a, int b)
    {
        Console.WriteLine(a + b);
    }
    static void Main(string[] args)
    {
        Program obj = new progrmm1();
        Program obj1 = new Program();

        obj.CalculateArea(4, 5);
        obj1.CalculateArea(4, 5);
        Console.ReadLine();
    }
}

答案 2 :(得分:0)

这样只允许使用update {/ p>添加key=value新密钥

 class MyDict(dict):
    def __init__(self, d):
        dict.__init__(self)
        self.instant = False
        self.update(d)

    def update(self, other=None, **kwargs):
        if other is not None:
            if isinstance(other, dict):
                for k, v in other.items():
                    self[k] = v
            else:
                for k, v in other:
                    self[k] = v
        else:
            dict.update(self, kwargs)
        self.instant = True

    def __setitem__(self, key, value):
        if self.instant and key not in self:
            raise KeyError(key)
        dict.__setitem__(self, key, value)

x = MyDict({1:2,2:3})
x[1] = 100 # works
x.update(cat=1) # works
x.update({2:200}) # works 
x["bar"] = 3 # error
x.update({"foo":2}) # error
x.update([(5,2),(3,4)])  # error