Home > Software design >  Python OOP question, one class's value is not updated by another class's function
Python OOP question, one class's value is not updated by another class's function

Time:06-01

I'm making a simple "bill split" situation with OOP and for some reason, the item's "partition price" (updates whenever more users pitch in for that item; ex: 1 person wants a $5 item = $5 partition price, 2 people want it = $2.5 partition price, ...).

For some reason, the "owes" in Participant and the partition_price in Item don't want to update and I can't figure out what's going wrong.

class Participant:

    #Participant has a name and has items he wants to pitch in for
    def __init__(self, name):
        self.name = name
        self.items = []
        self.owes = []

    #Append the item (Item class) to the item list
    #Append participant's name to the item's participant list
    #Append the item's partition price $ to the owes list
    def add_Item(self, item):
        self.items.append(item)
        item.participants.append(self.name)
        self.owes.append(item.partition_price)

class Item:

    #Item has a name and a price
    def __init__(self, name, price):
        self.name = name
        self.price = price

        #List of participants that are pitching in for the item
        self.participants = []

        #If the list of participants is empty (no participants)
        if not self.participants:
            #The cost of a "pitch in" for this item is $0
            self.partition_price = 0

        #Otherwise, the cost of a "pitch in" for this item is its price/number of participants
        else:
            self.partition_price = price/len(self.participants)

#Create 2 people
matthew = Participant('Matthew')
bob = Participant('Bob')

#Create an item
juice = Item('Apple Juice', 2.99)

#These 2 people wants that item
matthew.add_Item(juice)
bob.add_Item(juice)

#Test
print(f'Matthew wants: {[i.name for i in matthew.items]}')
print(f'Who wants Apple Juice: {juice.participants}')
print(f'Matthew owes: {matthew.owes}')


print(f'The juice costs: {juice.price}, so each person owes: {juice.partition_price} <-- class function')
print(f'The juice ocsts: {juice.price}, so each person owes: {juice.price/len(juice.participants)} <-- external function')

This is what it prints:

Matthew wants: ['Apple Juice']
Who wants Apple Juice: ['Matthew', 'Bob']
Matthew owes: [0]
The juice costs: 2.99, so each person owes: 0 <-- class function
The juice ocsts: 2.99, so each person owes: 1.495 <-- external function

Matthew should owe 1.495 at the 3rd print statement. The 4th print statement should also print 1.495. Only the external function works.

CodePudding user response:

your partition_price is being calculated during the initialization of Item when you first create juice in line juice = Item('Apple Juice', 2.99), participants will be an empty list which result in partition_price being 0.

You subsequently calls the add_Item function for matthew and bob which adds them as participant in juice, which explains why juice.price/len(juice.participants) returns 1.495

You might want to have a add_participant method in Item instead of calling item.participants.append(self.name) where it adds a participant to self.participants and calculates the self.partition_price

class Participant:

#Participant has a name and has items he wants to pitch in for
def __init__(self, name):
    self.name = name
    self.items = []
    self.owes = []

#Append the item (Item class) to the item list
#Append participant's name to the item's participant list
#Append the item's partition price $ to the owes list
def add_Item(self, item):
    self.items.append(item)
    item.add_participant(self.name)
    self.owes.append(item.partition_price)

class Item:

    #Item has a name and a price
    def __init__(self, name, price):
        self.name = name
        self.price = price

        #List of participants that are pitching in for the item
        self.participants = []

        #If the list of participants is empty (no participants)
        if not self.participants:
            #The cost of a "pitch in" for this item is $0
            self.partition_price = 0

        #Otherwise, the cost of a "pitch in" for this item is its price/number of participants
        else:
            self.partition_price = price/len(self.participants)
        
        
    def add_participant(self, name):
        self.participants.append(name)
        self.partition_price = self.price / len(self.participants)

#Create 2 people
matthew = Participant('Matthew')
bob = Participant('Bob')

#Create an item
juice = Item('Apple Juice', 2.99)

#These 2 people wants that item
matthew.add_Item(juice)
bob.add_Item(juice)

#Test
print(f'Matthew wants: {[i.name for i in matthew.items]}')
print(f'Who wants Apple Juice: {juice.participants}')
print(f'Matthew owes: {matthew.owes}')


print(f'The juice costs: {juice.price}, so each person owes: {juice.partition_price} <-- class function')
print(f'The juice ocsts: {juice.price}, so each person owes: {juice.price/len(juice.participants)} <-- external function')

Output:

Matthew wants: ['Apple Juice']
Who wants Apple Juice: ['Matthew', 'Bob']
Matthew owes: [2.99]
The juice costs: 2.99, so each person owes: 1.495 <-- class function
The juice ocsts: 2.99, so each person owes: 1.495 <-- external function
  • Related