Python equivalent for comparison

I have a dictionary like this:

{ <Category('Simulate', 'False', 'False', 'False', 'INTERMEDIATE')>: {'link': u'/story/4/tvb-adapters-simulator-simulatorAdapter/SimulatorAdapter', 'name': u'Simulate'}, <Category('View Results', 'True', 'False', 'True', 'INTERMEDIATE')>: {'link': '/story/step/3', 'name': u'View Results'}, <Category('Analyze', 'True', 'False', 'False', 'FINAL')>: {'link': '/story/step/2', 'name': u'Analyze'}} 

A category is a class that represents an instance from a database. Now I have the following example:

  <Category('Analyze', 'True', 'False', 'False', 'FINAL')> 

Now this is not the same instance. By this I mean that I get all the values ​​from the database and create a dictionary. Then after a while I get the identifier and retrieve the instance from the database. Now they are not the same objects. Now I have to check this in the dictionary, but:

 instance in disctionary 

Will return false. Now I could go in an ugly way and retry the dictionary check if all values ​​match, however is there a smarter way for Python to do this? I mean something like the Comparable equivalent in Java?

+6
source share
5 answers

First: use True and False (boolean properties) instead of 'True' and 'False' (string properties).

Generally, you can make everything comparable in Python. You just need to define specific methods (e.g. __eq__ , __lt__ , etc.) for your class.

So, let's say I want to compare instances of class A, and the comparison should just be an indifferent string comparison of the s element:

 class A(object): def __init__(self, s=''): self.s = s def __eq__(self, other): return self.s.lower() == other.s.lower() a = A('aaaa') b = A('AAAA') print a == b # prints True b = A('bbbb') print a == b # prints False 
+9
source

Instead of using Category instances (e.g. Category('Analyze', 'True', 'False', 'False', 'FINAL') ) as keys in the dictionary, it looks like you should use a linked tuple (like ('Analyze', 'True', 'False', 'False', 'FINAL') ).

If you really want to use the Category instance as keys in the dictionary, you will need to define both __hash__ and __eq__ . For instance:

 class Category(object): def __init__(self,*args): self.args=args def __hash__(self): # Note that this assumes that Category hash value is immutable # ie self.args does not change. return hash(self.args) def __eq__(self,other): return self.args == other.args a=Category('Analyze', 'True', 'False', 'False', 'FINAL') b=Category('Analyze', 'True', 'False', 'False', 'FINAL') mydict={a:1} 

a and b are different instances, so they have different id s, but their hash values ​​are the same:

 assert id(a) != id(b) assert hash(a)==hash(b) 

This shows that b is an acceptable key in mydict :

 print(mydict[a]) # 1 print(mydict[b]) # 1 

PS. Do not worry __cmp__ . In Python 3 :

The cmp () function should be considered lost, and the __cmp__() special method is no longer supported. Use __lt__() to sort, __eq__() with __hash__() and other rich comparisons as needed.

+2
source

There may be shortcuts, for example, using tuples, but the general answer to your question is: implement __eq__() for your class so that cmp () uses it instead of testing for identification.

+1
source

For in and other comparison operators to work, you must implement __hash__ and __cmp__ (or "rich" comparison methods, such as __eq__ ). See Python Link .

+1
source

As you can apparently put instances of your category in a dict, you should already overwrite __hash__ . Now you need __eq__ :

 class Category(object): # you must have overwritten `__hash__` like this already def __hash__(self): return hash((self.attr1, self.attr2, ... )) # now you just need tis def __eq__(self, other): return isinstance(other, Category) and \ (self.attr1, self.attr2, ... ) == (other.attr1, other.attr2, ... ) 

What you really have to do is throw away this whole class and use collections.namedtuple instead:

 Category = collections.namedtuple('Category', 'attr1 attr2 attr3') 
+1
source

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


All Articles