Byte
Byte

Reputation: 509

How would I make a loop that creates instances in python 3?

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

Answers (1)

martineau
martineau

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

Related Questions