metaclasses for type comparison

S

Simon Burton

In today's experiment, I was wondering if I could make the comparison
operators (<,<=,>=,>) work on classes (types) according to inheritance.

The idea is, for example, classes lower in the class hierarchy would be
less than (more specialized) than classes they inherit from.

class A(object):
pass

class B(A):
pass

B < A # should be True

In my first attempt I tried putting __lt__ into the class definition for A
and then assigning it as a staticmethod. This doesn't work, but something
was happening; <,<=,>=,> are still valid as applied to classes.

Because class is to instance as metaclass is to class, I found that the
place to put these methods is in the class' metaclass.

class MetaCMP(type):
def __lt__(cls,other):
for base in cls.__bases__:
if type(base) != cls.__class__:
continue
if base <= other:
return 1
return 0

def __le__(cls,other):
if cls == other:
return 1
for base in cls.__bases__:
if type(base) != cls.__class__:
continue
if base <= other:
return 1
return 0

def __gt__(cls,other):
for base in other.__bases__:
if type(base) != cls.__class__:
continue
if cls >= base:
return 1
return 0

def __ge__(cls,other):
if cls == other:
return 1
for base in other.__bases__:
if type(base) != cls.__class__:
continue
if cls >= base:
return 1
return 0

__metaclass__ = MetaCMP

Now, with the above code, we can replace a call to isinstance.

type( B() ) <= A # True

It seems natural enough to my math trained eye.

But now we have non-comparible objects, which confuses the sorting issue.

class C:
pass

C < A # False
A < C # False

For example, if we wanted a "total" order ( always either X<=Y or Y<=X )
we could remove __ge__ and __gt__ from MetaCMP. It's not clear to me
exactly which comparison methods "list.sort" uses. (The ideal sort here is
the topological sort.)

I also thought about extending this order so that "B() <= A" would behave
the same way. It would be rather more strange. Is it so natural that an
instance is "smaller" than it's type? Perhaps; the instance can have
attributes that override it's type, which is reminiscent of some kinds of
inheritance.

Finally, the feature request. If "type" implemented these semantics for
comparison would it break existing code? Does anyone rely on "1<dict"
being True, or that we have a total order (one of "<","==" or ">" always
True) ? Another quandry is that one could just as naturally argue for the
reverse ordering.

Comments sought (can you guess what + might do to classes?).

Simon Burton.
 
D

David C. Fox

Simon said:
In today's experiment, I was wondering if I could make the comparison
operators (<,<=,>=,>) work on classes (types) according to inheritance.

The idea is, for example, classes lower in the class hierarchy would be
less than (more specialized) than classes they inherit from.

class A(object):
pass

class B(A):
pass

B < A # should be True

Is this an exercise to help you learn about metaclasses, or do you
actually want to be able to check whether B is a subclass of A. If the
latter, then try issubclass(B, A). Otherwise, ignore this comment

David
 
S

Simon Burton

On Thu, 11 Sep 2003 03:03:02 +0000, David C. Fox wrote:

....
Is this an exercise to help you learn about metaclasses, or do you
actually want to be able to check whether B is a subclass of A. If the
latter, then try issubclass(B, A). Otherwise, ignore this comment

David

Both. Well, aha, "issubclass" makes my implementation
of ge/le and friends a bit silly. Actually i was annoyed
with "isinstance", it seems like it should be part of the syntax
(eg."<="). Look at this: "issubclass". It has 10 chars!!

Lazy when i can be,

Simon Burton.
 
D

David Eppstein

Simon Burton said:
Both. Well, aha, "issubclass" makes my implementation
of ge/le and friends a bit silly. Actually i was annoyed
with "isinstance", it seems like it should be part of the syntax
(eg."<="). Look at this: "issubclass". It has 10 chars!!

<= is supposed to be a total ordering, so it is not a good idea to use
it for partial orders such as subclass hierarchies.
 
G

Gonçalo Rodrigues

<= is supposed to be a total ordering, so it is not a good idea to use
it for partial orders such as subclass hierarchies.

Is it? I never came across such a supposition, which in itself says
nothing because I have very little experience anyway, but what about
set inclusion in the sets module which can be written as <=?

With my best regards,
G. Rodrigues
 
D

David Eppstein

<= is supposed to be a total ordering, so it is not a good idea to use
it for partial orders such as subclass hierarchies.

Is it? I never came across such a supposition, which in itself says
nothing because I have very little experience anyway, but what about
set inclusion in the sets module which can be written as <=?[/QUOTE]

I don't have 2.3 yet, so haven't used sets yet, but what happens if you
try to sort a list of sets?

I found a message
<http://mail.python.org/pipermail/python-bugs-list/2003-January/015454.h
tml> from Guido wondering about this but didn't see what the response
was...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top