[Tutor] __cmp__() method examples?

Rob McGee i812@iname.com
Wed, 5 Dec 2001 21:35:47 -0600


I haven't found many examples of how to do a Class.__cmp__() method. I
have a class whose instances have a certain alphabetic value which
should always be unique. I figured I would only be comparing these class
instances to other instances of the same class, so I chose to compare
based on that alphabetic value.

Maybe an example will clarify:

{code}
import random

class Project:
  def __init__(self, name):
    self.name = name
    self.value = random.randrange(1, 100)
  def __str__(self):
    return self.name
  def __cmp__(self, other):
    if self.name < other.name:  # compare name value (should be unique)
      return -1
    elif self.name > other.name:
      return 1
    else: return 0              # should mean it's the same instance

# now generate class instances -- this is always done automatically
from string import uppercase
for letter in uppercase:
  execStr = letter + ' = Project("' + letter + '")'
  # example -- 'A = Project("A")', 'Z = Project("Z")
  exec(execStr)

{/code}

(Sorry about the exec's, but I really don't know another way to do what
I want. I want these instances in the global namespace, and I need to
know exactly what each one is named. At least I think I do. Suggestions
about other ways to approach this would be welcomed, too. :) Like with
no exec's, or with the instances in something other than globals(), how
would I be able to retrieve and alter their properties?)

The user interacts with these class instances through code like this:

{code}
def getProjectName():
  text = raw_input('Project name: ')
  text = text.upper()
  return text

def objectEntry(text):
  """converts text to an object name"""
  try:
    object = eval(text)
    return object
  except: return

def ifInstance(object, className=Project):
  """returns object if it's an instance of className"""
  try:
    if object.__class__ == className:
      return object
  except: return

def myStupidMenu():
  keepGoing = 1
  while keepGoing:
    prompt = 'stupid menu ("g/x"): '
    choice = raw_input(prompt)
    choice = choice.upper()
    if choice == "G":
      text = getProjectName()
      if text:
        object = objectEntry(text)
        if object:
          instance = ifInstance(object)
          print instance, '=', instance.value
    elif choice == "X":
      keepGoing = 0
    else:
      print "\tyou're as stupid as this menu!"

myStupidMenu()
{/code}

I'm getting errors which indicate that the class instances are being
compared with other objects (AttributeError: object has no "name"
attribute.) I don't know if the sample code here will generate those
errors -- probably not -- but what I'm hoping for is just a little
guidance on how to properly implement a __cmp__() method.

What I think I'll try -- the idea came to me while writing this :) -- is
to put code in Project.__cmp__() like the ifInstance() above. If "other"
isn't an instance of self.__class__, don't try to get other.name.

Oh, I should also mention that I got into an infinite loop with another
class.__cmp__() method. That class was more complicated, and I had
several if/elif loops to compare other attributes. The fourth and final
such loop simply compared "self" and "other". I believe that was where
the loop occurred, and it was in sorting a list of instances of that
class (I don't think there were any non-instance members of the list.)

By removing the self/other raw comparison I eliminated the infinite
loop. But that experience gives me the idea that I'm missing something
about how to do a Class.__cmp__().

Thanks again all,

    Rob - /dev/rob0