Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: Python: Python

Elegant compare

 

 

Python python RSS feed   Index | Next | Previous | View Threaded


jsf80238 at gmail

Aug 10, 2013, 8:41 PM

Post #1 of 4 (22 views)
Permalink
Elegant compare

class my_class:
def __init__(self, attr1, attr2):
self.attr1 = attr1 #string
self.attr2 = attr2 #string
def __lt__(self, other):
if self.attr1 < other.attr1:
return True
else:
return self.attr2 < other.attr2

I will run into problems if attr1 or attr2 is None, and they
legitimately can be.

I know I can check for attr1 or attr2 or both being None and react
accordingly, but my real class has ten attributes and that approach
will be long. What are my alternatives?
--
http://mail.python.org/mailman/listinfo/python-list


rosuav at gmail

Aug 10, 2013, 8:45 PM

Post #2 of 4 (21 views)
Permalink
Re: Elegant compare [In reply to]

On Sun, Aug 11, 2013 at 4:41 AM, Jason Friedman <jsf80238 [at] gmail> wrote:
> class my_class:
> def __init__(self, attr1, attr2):
> self.attr1 = attr1 #string
> self.attr2 = attr2 #string
> def __lt__(self, other):
> if self.attr1 < other.attr1:
> return True
> else:
> return self.attr2 < other.attr2
>
> I will run into problems if attr1 or attr2 is None, and they
> legitimately can be.
>
> I know I can check for attr1 or attr2 or both being None and react
> accordingly, but my real class has ten attributes and that approach
> will be long. What are my alternatives?

The first question is: What should the comparison do with a None
value? Should it be considered less than every string? If so, you
could simply use:

if (self.attr1 or "") < (other.attr1 or ""):

which will treat any falsy value as blank.

ChrisA
--
http://mail.python.org/mailman/listinfo/python-list


steve+comp.lang.python at pearwood

Aug 11, 2013, 1:26 AM

Post #3 of 4 (14 views)
Permalink
Re: Elegant compare [In reply to]

On Sat, 10 Aug 2013 21:41:00 -0600, Jason Friedman wrote:

> class my_class:
> def __init__(self, attr1, attr2):
> self.attr1 = attr1 #string
> self.attr2 = attr2 #string
> def __lt__(self, other):
> if self.attr1 < other.attr1:
> return True
> else:
> return self.attr2 < other.attr2
>
> I will run into problems if attr1 or attr2 is None, and they
> legitimately can be.
>
> I know I can check for attr1 or attr2 or both being None and react
> accordingly, but my real class has ten attributes and that approach will
> be long. What are my alternatives?

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 isinstance" check into a
decorator, but since the decorator is likely to be about six lines long,
I wouldn't bother :-)



--
Steven
--
http://mail.python.org/mailman/listinfo/python-list


jsf80238 at gmail

Aug 11, 2013, 8:17 AM

Post #4 of 4 (7 views)
Permalink
Re: Elegant compare [In reply to]

> 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?

Yes, my code snippet was too short, I should have said:

class my_class:
def __init__(self, attr1, attr2, attr3):
self.attr1 = attr1 #string
self.attr2 = attr2 #string
self.attr3 = attr3 #string
def __lt__(self, other):
if self.attr1 < other.attr1:
return True
elif self.attr2 < other.attr2:
return True
else:
return self.attr3 < other.attr3

Chris's answer is actually perfectly adequate for my needs.
Thank you Steve and Chris.
--
http://mail.python.org/mailman/listinfo/python-list

Python python RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact Gossamer Threads
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.