Overwriting special functions in Python

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 a built-in dict. I want to allow users to define custom validation functions for both a key and values ​​in my special dictionary, for example:

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, for example:

 def update(self,key,value): assert (self.keyValidator(key)) assert (self.valueValidator(key)) self[key] = value 

But this will not work if someone decides to just go and use [] as access. Or, if someone creates an object using a dictionary literal.

 mySpecialDict = SpecialDict mySpecialDict['hello'] = 54 
+4
source share
4 answers

Someone cannot create an instance of your SpecialDict as a dictionary, because that is the dictionary literal; normal dictionary.

As for setting elements with a quadratic note, as in mySpecialDict['hello'] = 54 , this only mySpecialDict.__setitem__('hello', 54) . Similarly, getting an element with a square bracket corresponds to calling the __getitem__ method. This is true no matter which class mySpecialDict ; be it a regular dictionary, a class that subclasses an inline dict or some completely unrelated class. Therefore, you can simply implement these methods to change what they do (using super(SpecialDict, self).__setitem__(key, value) or dict.__setitem__(self, key, value) to refer to the normal implementation when you necessary).

One problem you will encounter is that some (all?) __getitem__ implementations of other dict methods will not respect your overridden __setitem__ or __getitem__ . Therefore, you cannot inherit them; you will have to redefine all of them and either completely repeat them in terms of your versions of the basic operations, or at least perform your checks around the superclass calls.

A less painful approach might be to not subclass the inline dict and instead implement its own "dict-like" object, which wraps a regular dictionary using the base classes collections.Mapping or collections.MutableMapping to get a dictionary interface. Using this approach, you only need to implement about 6 basic methods (what you would do by including the verification logic around calls in a wrapped dictionary) and get reasonable definitions of other methods based on them. See http://docs.python.org/library/collections.html#collections-abstract-base-classes

+4
source

You can override the special __getitem__ method to implement your [] operator behavior. For more information, see this .

+2
source

Thunder!

I am on a mobile device, so I can’t give a complete answer, but I will look at __getitem__ and __setitem__

0
source

You can override the __setitem__(self, key, val) method and use super(SpecialDict, self).__setitem__ to access the method of the parent object (i.e. dict s):

 class SpecialDict(dict): def __init__(self, keyValidator = lambda x:True, valueValidator = lambda x:True): self.keyValidator = keyValidator self.valueValidator = valueValidator def __setitem__(self, key, val): assert (self.keyValidator(key)) assert (self.valueValidator(val)) super(SpecialDict, self).__setitem__(key, val) 

Also note the use of lambdas as default values: using just True or False will result in an error, since they cannot be called.

0
source

Source: https://habr.com/ru/post/1413073/


All Articles