This is a hard question to answer, because your code snippet isn't clearly extensible to the case where you have ten attributes. What's the rule for combining them? If instance A has five attributes less than those of instance B, and five attributes greater than those of instance B, which wins?
But if I had to guess an approach, I'd start with a helper function (or method) that compares two raw values:
def compare(a, b):
"Return -ve for less than, 0 for equal, +ve for greater than."
if a is None:
return 0 if b is None else -1
if b is None:
return 1
return (b < a) - (a < b)
Now, in your class, you can use this helper function to check each attribute in turn. Assuming that if an attribute is equal, you move on to check the next one:
class MyClass:
def _compare(self, other):
for attr in 'attr1 attr2 attr3 attr4'.split():
a, b = getattr(self, attr), getattr(other, attr)
triflag = compare(a, b)
if triflag:
return triflag
return 0
def __lt__(self, other):
if not isinstance(other, MyClass):
return NotImplemented
return self._compare(other) < 0
def __eq__(self, other):
if not isinstance(other, MyClass):
return NotImplemented
return not self._compare(other)
def __ne__(self, other):
if not isinstance(other, MyClass):
return NotImplemented
return bool(self._compare(other))
and so on. You can save a certain amount of repetition (by my count, six lines of code) by pulling out the "if not is instance" check into a decorator, but since the decorator is likely to be about six lines long, I wouldn't bother :-)