views:

160

answers:

3

Good day pythonians,

I want to make a custom dictionary with two main features:

  1. All keys are declared on creation
  2. It is impossible to add new keys or modify current ones (values are still modifiable)

Right now code is this:

class pick(dict):
   """This will make delicious toffee when finished"""
   def __init__(self, *args):
       dict.__init__(self)
       for arg in args:
           self[arg] = None

Any help is much appreciated.

upd:

While solution is what I was looking for there is one problem:

dictionary calls the __setitem__ to add the items on the initialization and not finding the keys it raises the error.

cupboard = pick('milk')  #raises error

upd1:

all solved, thank you very much.

+12  A: 

Override the __setitem__ method with your desired behavior, call dict.__setitem__(self, key, value) to modify the base dictionary without going through your base logic.

class ImmutableDict(dict):
    def __setitem__(self, key, value):
        if key not in self:
             raise KeyError("Immutable dict")
        dict.__setitem__(self, key, value)

d = ImmutableDict(foo=1, bar=2)
d['foo'] = 3
print(d)
d['baz'] = 4 # Raises error

You'll also need to override dict.update() and setdefault() to avoid addition of keys. And possibly dict.__delitem__(), dict.clear(), dict.pop() and dict.popitem() to avoid removal of keys.

Ants Aasma
+2  A: 

Something like

def __setitem__(self, name, value):
    if name not in self:
        raise KeyError("%s not present")
    dict.__setitem__(self, name, value)
Eli Courtwright
+2  A: 

I suggest you to use delegation, rather than inheritance. If you inherit, all the previous methods of the dict will be inherited, but they could behave as you don't expect, thus ruining the assumptions you have on the class, and doing it silently.

If you do delegation, you can fully control the methods you provide, and if you try to use your dict in a context requiring a method you have not implemented, you will get an exception, failing fast to the problem.

Stefano Borini
While you raise an interesting point, dict is a pretty transparent class and it's not hard to verify that you've covered all the possibilities for setting keys. So I would not recommend delegation.
David Zaslavsky
yep. Got burned by inheritance. Now I am very careful ;)
Stefano Borini