Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Can you make this __eq__ easy to understand?

I have another question for you.

I have a python class with a list 'metainfo'. This list contains variable names that my class might contain. I wrote a __eq__ method that returns True if the both self and other have the same variables from metainfo and those variables have the same value.

Here is my implementation:

 def __eq__(self, other):
    for attr in self.metainfo:
      try:
        ours = getattr(self, attr) 
        try:
          theirs = getattr(other, attr)
          if ours != theirs:
            return False
        except AttributeError:
          return False
      except AttributeError:
        try:
          theirs = getattr(other, attr)
          return False
        except AttributeError:
          pass
    return True

Does anyone have any suggestions as to how I can make this code easier on the eye? Be as ruthless as you please.

like image 545
pisswillis Avatar asked Nov 27 '22 06:11

pisswillis


2 Answers

Use getattr's third argument to set distinct default values:

def __eq__(self, other):
    return all(getattr(self, a, Ellipsis) == getattr(other, a, Ellipsis)
               for a in self.metainfo)

As the default value, set something that will never be an actual value, such as Ellipsis. Thus the values will match only if both objects contain the same value for a certain attribute or if both do not have said attribute.

Edit: as Nadia points out, NotImplemented may be a more appropriate constant (unless you're storing the result of rich comparisons...).

Edit 2: Indeed, as Lac points out, just using hasattr results in a more readable solution:

def __eq__(self, other):
    return all(hasattr(self, a) == hasattr(other, a) and
               getattr(self, a) == getattr(other, a) for a in self.metainfo)

  : for extra obscurity you could write ... instead of Ellipsis, thus getattr(self, a, ...) etc. No, don't do it :)

like image 81
Stephan202 Avatar answered Nov 29 '22 20:11

Stephan202


I would add a docstring which explains what it compares, as you did in your question.

like image 24
Bastien Léonard Avatar answered Nov 29 '22 20:11

Bastien Léonard