Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Comparing objects - is there a maximum object?

0 views
Skip to first unread message

Chris Brew

unread,
Sep 4, 2003, 3:24:38 PM9/4/03
to
I've just been writing some code to merge items from
a collection of streams, where each item has a key,
and each stream is known to be sorted in ascending
order of key. I read all the streams once, then
pick the minimum element of the results, replace
it with a new one read from the corresponding
stream, and repeat.

Thing is, what happens at end of file? I'd like to
do it by making the streams that are finished
return some object (call it endmarker) such
that min(x,endmarker) always returns x. That way,
when all the streams are returning endmarker, we
would be done. And I'd like my code to work the same
no matter what kind of thing the streams are
returning, so I want endmarker to be a generic
maximum object.

The Python documentation says:

The operators <, >, ==, >=, <=, and != compare the values of two
objects. The objects need not have the same type. If both are numbers,
they are converted to a common type. Otherwise, objects of different
types always compare unequal, and are ordered consistently but
arbitrarily

so (unless this has been superseded) it doesn't seem that there is
such an object. Any suggestions? I notice that empirically max(x,None)
seems to be always x, but again I suppose I shouldn't count on that.

Chris

"Martin v. Löwis"

unread,
Sep 4, 2003, 3:47:09 PM9/4/03
to
Chris Brew wrote:

> so (unless this has been superseded) it doesn't seem that there is
> such an object. Any suggestions?

The easiest way to produce a maximum object is

class Max:
def __cmp__(self, other):
return 1
maximum = Max()

HTH,
Martin

Andrew Dalke

unread,
Sep 4, 2003, 5:09:17 PM9/4/03
to
Martin v. Löwis:

> The easiest way to produce a maximum object is
>
> class Max:
> def __cmp__(self, other):
> return 1

Shouldn't there also be a

def __rcmp__(self, other):
return -1
?

Andrew
da...@dalkescientific.com


Martin v. Löwis

unread,
Sep 4, 2003, 6:38:15 PM9/4/03
to
"Andrew Dalke" <ada...@mindspring.com> writes:

> Shouldn't there also be a
>
> def __rcmp__(self, other):
> return -1
> ?

No, this would not be used. cmp(a,b) == -cmp(b,a)

Regards,
Martin

Mel Wilson

unread,
Sep 4, 2003, 7:00:20 PM9/4/03
to
In article <7bdbb1a6.03090...@posting.google.com>,
cb...@acm.org (Chris Brew) wrote:
> [ ... ] so I want endmarker to be a generic
>maximum object.

I've used the following.. a module I call limitcases.py.
It ensures that limit objects compare equal to each other,
and have distinctive hash values, so they work as sort keys
and can be used as dictionary keys.

Regards. Mel.


"""limitcases.py
Provides objects which compare less-than and greater-than any other object.
Useful for sentinels, or for initial values in maximum- or minimum-finding
routines.
"""

class Lowest:
"Instances of Lowest compare < any object except each other."
def __cmp__ (self, other):
if isinstance (other, Lowest):
return 0
return -1

def __hash__ (self):
return id (Lowest)
# class Lowest


class Highest:
"Instances of Highest compare > any object except each other."
def __cmp__ (self, other):
if isinstance (other, Highest):
return 0
return 1

def __hash__ (self):
return id (Highest)
# class Highest


if __name__ == '__main__':
print Lowest()
print Highest()
print

# An application can provide its own printable representation.
Lowest.__str__ = lambda x: "-Infinity"
Highest.__str__ = lambda x: "+Infinity"

x = [1, Highest(), 2, Lowest(), 0, Highest(), Lowest()]
x.sort()
print 'X = ',
for v in x:
print v,
print
print
print'X:', x
print

Peter Otten

unread,
Sep 5, 2003, 4:07:19 AM9/5/03
to
Chris Brew wrote:

> Thing is, what happens at end of file? I'd like to
> do it by making the streams that are finished
> return some object (call it endmarker) such
> that min(x,endmarker) always returns x. That way,
> when all the streams are returning endmarker, we
> would be done. And I'd like my code to work the same
> no matter what kind of thing the streams are
> returning, so I want endmarker to be a generic
> maximum object.
>

Why not remove "streams" that have reached the end?
You could do something like

def gen(*seqs):
seqs = [iter(seq) for seq in seqs]
done = []
while True:
result = []
for it in seqs:
try:
result.append(it.next())
except StopIteration:
done.append(it)
if len(done):
for d in done:
seqs.remove(d)
done = []
if len(result) == 0:
break
yield result

# produce sample data
import random
l1 = range(5)
l2 = range(10)
l3 = range(3, 6)
for l in l1, l2, l3:
random.shuffle(l)

# demonstration
for i, x in enumerate(gen(l1, l2, l3)):
print i, x, "-->", min(x)

There may be room for improvement in the gen() function, but the general
idea is not to compare objects made up only for that purpose and when you
already know the outcome.

Peter

Andrew Dalke

unread,
Sep 5, 2003, 9:48:48 PM9/5/03
to
Martin v. Löwis:

> No, this would not be used. cmp(a,b) == -cmp(b,a)

True. Unlike + and *, cmp is communitive.

Here's the results of some instrumentation under 2.3.

>>> class Max:
... def __getattr__(self, name):
... print "Looking for", name
... if name == "__cmp__":
... return lambda other: 1
... raise AttributeError(name)
...
>>> data = [Max(), 0, 1, 2, 3]
>>> data.sort()
Looking for __gt__
Looking for __coerce__
Looking for __cmp__
Looking for __gt__
Looking for __coerce__
Looking for __cmp__
Looking for __gt__
Looking for __coerce__
Looking for __cmp__
Looking for __gt__
Looking for __coerce__
Looking for __cmp__
>>> random.shuffle(data); data.sort(); data
Looking for __lt__
Looking for __coerce__
Looking for __cmp__
Looking for __repr__
[0, 1, 2, 3, <__main__.Max instance at 0x013D8C88>]

Not an __rcmp__ in the mix.

Andrew
da...@dalkescientific.com


0 new messages