Is there a way to overwrite special functions for built in types in python? For example, I want to create a SpecialDict class that inherits from the built in dict. I want to allow users to define custom validation functions for both key and values in my special dictionary, like so:
def __init__(self, keyValidator = True, valueValidator = True):
self.keyValidator = keyValidator
self.valueValidator = valueValidator
Using this, I can intercept the addition of values in the update method, like so:
def update(self,key,value):
assert (self.keyValidator(key))
assert (self.valueValidator(key))
self[key] = value
But this won’t work if someone decides to just go ahead and use the [] as access. Or if someone creates the object using a dictionary literal.
mySpecialDict = SpecialDict
mySpecialDict['hello'] = 54
Someone can’t create an instance of your
SpecialDictas a dictionary literal, because a dictionary literal is just that; a normal dictionary.As far as setting items with square bracket notation, as in
mySpecialDict['hello'] = 54, that just corresponds tomySpecialDict.__setitem__('hello', 54). Likewise retrieving an item with the square bracket notation corresponds to an invocation of the__getitem__method. This is true no matter what classmySpecialDictis; whether it’s an ordinary dictionary, a class that subclasses the builtindict, or some entirely unrelated class. So you can just implement those methods to change what they do (usingsuper(SpecialDict, self).__setitem__(key, value)ordict.__setitem__(self, key, value)to refer to the normal implementation, when you need to).One problem you will run into is that some (all?) of the builtin implementation of other dict methods will not respect your overridden
__setitem__or__getitem__. So you won’t be able to inherit them; you’ll have to override all of them and either completely re-implement them in terms of your versions of the basic operations, or at least run your validations “around” the superclass calls.A much less painful approach might actually be to not subclass the builtin dict, and instead implement a custom “dict-like” object that wraps an ordinary dictionary, using the
collections.Mappingorcollections.MutableMappingbase classes to get the dictionary interface. Using this approach you’ll only need to implement about 6 basic methods yourself (which you’d do by plugging in your validation logic around calls to the wrapped dictionary), and get sensible definitions of other methods based on them. See http://docs.python.org/library/collections.html#collections-abstract-base-classes