Python dictionary classes (which are class objects) are compared with multiple comparators

I use custom objects as keys in a python dictionary. These objects have a default hash and eq methods that are used in the default comparison. But in some function I need to use a different way to compare these objects. So, is there a way to override or pass a new mapper to compare these keys only for this particular function.

Updated: my class has the following type of functionality (I can’t edit the hash method here, it will affect a lot in other places)

class test(object): def __init__(self,name,city): self.name=name self.city=city def __eq__(self,other): hash_equality= (self.name==other.name) if(not hash_equality): #check with lower return (self.name.lower()==other.name.lower()) def __hash__(self): return self.name.__hash__() my_dict={} a=test("a","city1") my_dict[a]="obj1" b=test("a","city2") print b in my_dict #prints true c=test("A","city1") print c in my_dict #prints false print c in my_dict.keys() #prints true # my_dict[c] throw error 

This is normal functionality. But in one specific method, I want to override / or pass in a new custom resolver where the new hash code looks like

 def __hash__(self): return self.name.lower().__hash__() 

so c in my_dict returns ture

or my_dict[c] will return "obj1"

Sorry for so many updates.

As with sorting, we can pass the custom method as a comparator, is there a way to do the same here.

+6
source share
5 answers

now I use my own dict (a derived class of dict), which takes a comparative parameter as a parameter, and I redefined it contains getitems (), which checks and gives a value based on values ​​on a comparator.

0
source

The only way to do this job is to create a copy of your dictionary using the new hash and comparison function. The reason is that the dictionary must rephrase each stored key with a new hash function to make the search work as you wish. Since you cannot provide a custom hash function for the dictionary (it always uses one of the key objects), the best option is probably to wrap your objects in a type that uses your custom hash functions and comparison functions.

 class WrapKey(object): __init__(self, wrapee): self._wrapee = wrapee __hash__(self): return self._wrapee.name.lower().__hash__() __eq__(self, other): return self._wrapee.name == other._wrapee.name def func(d): d_copy = dict((WrapKey(key), value) for key, value in d.iteritems()) # d_copy will now ignore case 
+4
source

Check out the comparison methods you can define in the object.

Depending on what you want to do, __cmp__ may also be interesting.

0
source

Hack this situation a bit:

 class test(object): def __init__(self,name,city,hash_func=None): self.name=name self.city=city self.hash_func = hash_func def __eq__(self,other): return self.__hash__()==other.__hash__() def __hash__(self): if self.hash_func is None: return self.name.__hash__() else: return self.hash_func(self) my_dict={} a=test("a","city1") my_dict[a]="obj1" b=test("a","city2") print b in my_dict #prints true c=test("A","city1") print c in my_dict #Prints false c.hash_func = lambda x: x.name.lower().__hash__() print c in my_dict #Now it prints true 

You cannot change the hash stored in the dict, but you can change the use of the hash for the search. Of course, this leads to something strange like this.

 my_dict={} a=test("a","city1") my_dict[a]="obj1" a.hash_func = lambda x: 1 for key in my_dict: print key in my_dict # False 
0
source

Steps: Implement a custom key class and override the hash function and the equality function.

eg.

 class CustomDictKey(object): def __init__(self, param1, param2): self._param1 = param1 self._param2 = param2 # overriding hash and equality function does the trick def __hash__(self): return hash((self._param1, self._param2)) def __eq__(self, other): return ( ( self._param1, self._param2 ) == ( other._param1, other._param2) ) def __str__(self): return "param 1: {0} param 2: {1} ".format(self._param1, self._param2) 

main method

 if name == 'main': # create custom key k1 = CustomDictKey(10,5) k2 = CustomDictKey (2, 4) dictionary = {} #insert elements in dictionary with custom key dictionary[k1] = 10 dictionary[k2] = 20 # access dictionary values with custom keys and print values print "key: ", k1, "val :", dictionary[k1] print "key: ", k2, "val :", dictionary[k2] 

For more information, see Using a Custom Class as a Key in the Python Dictionary .

0
source

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


All Articles