Search code examples
pythonclasscomparisonsubclassing

Comparing class instances and attaining cumulative "score"


So, I have two instances of a class Person and I am trying to do some comparisons. sunis one of several attributes of each instance is defined by two randomly generated numbers. I have the following questions... Is creating a subclass like Match the right way to go about setting up this comparison? And I want an overall "score" compiled at the end of this comparison, can I do that without the for-loop?

Person1 = Person("Person1")
Person2 = Person("Person2")


class Match(Person):

    overall = 0

    def __init__(self, Person1, Person2):
        self.Person1 = Person1
        self.Person2 = Person2

    def suns (self): 
        if abs(Person1.sun - Person2.sun) == 2 or 4 or 8 or 10:
            overall += 4

        elif abs(Person1.sun - Person2.sun) == 3 or 9: 
            overall -= 6

        elif abs(Person1.sun - Person2.sun) == 6:
            overall += 3

        else:
            overall += 0

print Match.overall

EDIT To clarify what I am trying to do... I have some basic understanding of how the astrological birth chart compatibility services work and just for fun and practice I want to make a very basic version of that program run. For now, all the data is randomly generated and no user input is needed. Here is what the Person class looks like

from random import randint
from decimal import Decimal

def randomDecimal(a,b):
    return (randint(int(a), int(100.0 * b)))/100.0

class Person:

    def __init__(self, name):
        self.name=name
        self.sun = (randomDecimal(1, 12), randomDecimal(0, 30)) 
        self.moon = (randomDecimal(1, 12), randomDecimal(0, 30)) 
        self.mercury = (randomDecimal(1, 12), randomDecimal(0, 30))
        self.venus = (randomDecimal(1, 12), randomDecimal(0, 30))
        self.mars = (randomDecimal(1, 12), randomDecimal(0, 30))

    def printer(self):
        print "your Sun is in %f, at %f degrees" % (self.sun[0], self.sun[1])
        print "your Moon is in %f, at %f degrees" % (self.moon[0], self.moon[1])
            #and so on and so forth for the printer

Solution

  • If you are trying to compare two people, the comparison itself isn't also a person.

    Python classes have special methods you can overide that allow inbuilt python equalities to work.

    For example:

    class Person():
        __init__(self, name="Sinead OConnor", etc...):
            # boiler plate goes here
            self.name = name
    
        __eq__(self, anotherPerson):
            return False # Perople are wonderful and unique and have no equal
    
        __cmp__(self,anotherPerson):
            return anotherPerson == "You" # Nothing compares too you!
    

    These will then allow you to do things like:

    > a = Person(a)
    > b = Person(b)
    > a == b
    False
    

    Obviouusly, how to compare people is difficult and application specific, but once the logic is in it makes sence.

    For your work, where you need to compare to people in the abstract "are they a good fit" sence, `cmp won't work as thats just is one thing greater than, less than or equal to another.

    In those cases, you can do the following

    class Person():
        delta = 100 # How close do 2 things need to be to be a good match
        __init__(self, name="Sinead OConnor", etc...):
            # boiler plate goes here
            self.name = name
    
        def loveOfPowerBallads(self,myRank):
            if 0<myRank<100:
                raise OutOfRange # Or whatever
            self.rankPowerBallads = myRank
    
        def isGoodMatch(self,otherPerson):
            return (self.rankPowerBallads - other.rankPowerBallads) ^ 2 < Person.delta
    

    Then:

    > ls = Person("legoStormtrooper")
    > ls.loveOfPowerBallads(95)
    > lp = Person("Lame Person")
    > ls.loveOfPowerBallads(30)
    > ls.isGoodMatch(lp)
    False
    

    Edit: Making it more specific for you (although the principle is the same):

    class Person:
    
        def __init__(self, name):
            self.name=name
            self.sun = (randomDecimal(1, 12), randomDecimal(0, 30)) 
            self.moon = (randomDecimal(1, 12), randomDecimal(0, 30)) 
            # etc...
    
        def compare(self,other):
            overall = 0
            if abs(self.sun - other.sun) in [2,4,8,10]:
                overall += 4
            elif abs(self.sun - other.sun) in [3,9]: 
                overall -= 6
            elif abs(self.sun - other.sun) == 6:
                overall += 3
            else:
                overall += 0
            return overall