[Tutor] Implementation of list comparison operators, was Re: Doubt in Python

Peter Otten __peter__ at web.de
Thu Jan 17 10:34:27 EST 2019


Alan Gauld via Tutor wrote:

> On 17/01/2019 07:24, Maninath sahoo wrote:
> >>>> a=[100,50,30]
> >>>> b=[100,90,3]
> >>>> a<b
> > True
> >>>> a>b
> > False
> >
> >
>> How it compares between two lists
>>
> The algorithm is probably described somewhere in the documentation
> but my understanding is that it looks something like this(in pdeudo code):

> def isGreater(X,Y):
> 
>    if len(X) <= len(Y) return False
> 
>    if X[0] < Y[0] return False
> 
>    if X[0] == Y[0] return X[1:] > Y[1:]
> 
>    return True
> 
> 
> And similarly for the other operators.
> 
> But that's just based on playing with the interpreter and exploring
> different values...

>>> [10] > [1, 2, 3]
True
>>> [1] > [10, 2, 3]
False

So you cannot decide on length alone.

My analogy of list comparison would be words in a dictionary; you compare 
individual letters until you reach a decision:

mad <--> mad

m -> equal
a -> equal
d -> equal
(no character on both sides) --> mad == mad

madam <--> mad

m -> equal
a -> equal
d -> equal
a is greater than (no character) --> madam > mad

madam <--> man

m -> equal
a -> equal
d is less than n --> madam < man


A tentative implementation of less() (untested):

# zip() intentionally omitted

def less(x, y):
    for i in range(min(len(x), len(y))):
        if not x[i] == y[i]:
            return x[i] < y[i]
    return len(x) < len(y)

Finally here's a tool that wraps all comparison operations of the list 
items.

$ cat track_compare.py
class A:
    def __init__(self, value):
        self.value = value
    def __lt__(self, other):
        print(self, "<?", other)
        return self.value < other.value
    def __eq__(self, other):
        print(self, "==?", other)
        return self.value == other.value
    def __gt__(self, other):
        print(self, ">?", other)
        return self.value > other.value
    def __le__(self, other):
        print(self, "<=?", other)
        return self.value <= other.value
    def __ge__(self, other):
        print(self, ">=?", other)
        return self.value >= other.value
    def __ne__(self, other):
        print(self, "!=?", other)
        return self.value != other.value
    def __repr__(self):
        return repr(self.value)


def noisy(items):
    return [A(item) for item in items]

a = noisy([1, 2, 3])
b = noisy([1, 10, 20])
c = noisy([1])
d = noisy([1])

print("{} < {}".format(a, b))
a < b

print("\n{} != {}".format(c, d))
c != d

print("\n{} == {}".format(c, d))
c == d

$ python3 track_compare.py 
[1, 2, 3] < [1, 10, 20]
1 ==? 1
2 ==? 10
2 <? 10

[1] != [1]
1 ==? 1

[1] == [1]
1 ==? 1
$

I tried to instrument the list.__len__() method in a similar way, but the 
list's comparison methods do not use that overriden method.



More information about the Tutor mailing list