Reputation: 509
I've looked at questions like Creating instances in a loop but I need to create new instances with different values each time, not a bunch of clones of the instance.
Below, I have written a restaurant tip calculator (with tax) for instances of the class Bill. I wrote a class method that creates a new instance when the calculating for the first instance is complete.
While this works if I have the .py file open to keep adding new instances and calling all the class methods needed, it would be far more useful if I somehow created a loop that would create a new instance when I type "yes" in the self.choice of the second class method.
My previous attempts to make a loop resulted in creating unnamed instances. "Return Bill(example, example, example)" doesn't do it for me because I would not be able to call methods on that (I probably could but it would give headaches and would not be pythonic.) Nor would I be able to append that to a list.
persons = []
class Bill:
def __init__(self, check, tax, tip):
self.check = check
self.tax = tax
self.tip = tip
def addPersons(self):
self.choice = input("Do you want to calculate for another person?")
if self.choice == "Yes" or self.choice == "yes":
person2 = Bill(float(input("Check: ")), float(input("Tax: ")), float(input("Tip: ")))
return person2
else:
pass
def percent(self):
self.tax = self.tax/100
self.tip = self.tip/100
def calculate(self):
self.result_1 = self.check + (self.check * self.tax)
self.result_final = self.result_1 + (self.result_1 * self.tip)
self.difference = self.result_final - self.result_1
self.advice = self.result_1, "is your check with tax added.", self.difference, "is how much tip you need to pay.", self.result_final, "is your total."
return self.advice
a = Bill(float(input("Check: ")), float(input("Tax: ")), float(input("Tip: ")))
a.percent()
a.calculate()
print(a.advice)
persons.append(a)
b = a.addPersons()
b.percent()
b.calculate()
print(b.advice)
persons.append(b)
c = b.addPersons()
c.percent()
c.calculate()
print(c.advice)
persons.append(c)
Thank you for your time and help. :)
Upvotes: 0
Views: 249
Reputation: 123413
I would refactor the addPersons()
method out of the class and do things like what's shown below. Note I also made calculate()
automatically call percent()
so that doesn't have to be done externally.
This is a better design because it moves responsibility for interacting with the user and getting input outside of the class itself (which aren't really its concern). It also allows it to be used with different user interfaces or programmatically, say from data in a database or other container.
class Bill:
def __init__(self, check, tax, tip):
self.check = check
self.tax = tax
self.tip = tip
def percent(self):
self.tax = self.tax/100
self.tip = self.tip/100
def calculate(self):
self.percent()
self.result_1 = self.check + (self.check * self.tax)
self.result_final = self.result_1 + (self.result_1 * self.tip)
self.difference = self.result_final - self.result_1
self.advice = (self.result_1, "is your check with tax added.",
self.difference, "is how much tip you need to pay.",
self.result_final, "is your total.")
return self.advice
bills = []
while True:
choice = input("Do you want to calculate for another person?")
if choice.lower().startswith("y"):
break
bill = Bill(float(input("Check: ")), float(input("Tax: ")),
float(input("Tip: ")))
bill.calculate()
print(*bill.advice)
bills.append(bill)
The loop does not create named instances of the Bill
class. Instead it stores them all in a list called bills
. If you wanted to associate a person's name to each one, you could instead put them in a dictionary that was keyed by name.
bills = {}
while True:
choice = input("Do you want to calculate for another person?")
if choice.lower().startswith("y"):
break
person_name = input("Enter the name of the person: ")
if not person_name:
continue # ask about continuing again
bill = Bill(float(input("Check: ")), float(input("Tax: ")),
float(input("Tip: ")))
bill.calculate()
print("{}'s bill:".format(person_name))
print(*bill.advice)
bills[person_name] = bill
Upvotes: 3