Skip to content
Advertisement

Instead of using primitive methods, should I be using a data structure?

This is my current code for a tax calculator based on age. I think that it would be easier to update in the future if I used data structures when calculating the brackets. Could someone help me make sense of this?

while True: #Loop the whole program
    from datetime import datetime, date #Get the Age of from user input
    
    print("Please enter your date of birth (dd mm yyyy)")
    date_of_birth = datetime.strptime(input("--->"), "%d %m %Y")
    
    def calculate_age(born):
        today = date.today()
        return today.year - born.year - ((today.month, today.day) < (born.month, born.day))
    
    age = calculate_age(date_of_birth)
    
    print("You are " ,int(age), " years old.")
    
    #Get the Salary from user input
    def get_salary():
        while True:
            try:
                salary = int(input("Please enter your salary: "))
            except ValueError:
                print("You need to enter a number ")
            else:
                break
        return salary
    
    #Calculate the Amount that needs to be paid, using if,elif,else
    def contribution(age):
        if age <= 35:
            tax = (salary * 0.20)
        elif 36 <= age <= 50:
            tax = (salary * 0.20)
        elif 51 <= age <= 55:
            tax = (salary * 0.185)
        elif 56 <= age <= 60:
            tax = (salary * 0.13)
        elif 61 <= age <= 65:
            tax = (salary * 0.075)
        else:
            tax = (salary * 0.05)
    
        return tax
    
    #Print the amount 
    if __name__ == "__main__": # It's as if the interpreter inserts this at the top of your module when run as the main program.
        salary = get_salary() #get salary from get_salary()
        tax = contribution(age) #calculate the tax
        print("you have to pay", tax, " every month ")
    while True:
        answer = str(input("Do you need to do another calculation? (y/n): "))
        if answer in ("y", "n"):
            break
        print ("invalid input.")
    if answer == "y":
        continue
    else:
        print("Thank you for using this Calculator, Goodbye")
        break

So the code that I’m assuming that I need to change is:

#Calculate the Amount that needs to be paid, using if,elif,else
def contribution(age):
    if age <= 35:
        tax = (salary * 0.20)
    elif 36 <= age <= 50:
        tax = (salary * 0.20)
    elif 51 <= age <= 55:
        tax = (salary * 0.185)
    elif 56 <= age <= 60:
        tax = (salary * 0.13)
    elif 61 <= age <= 65:
        tax = (salary * 0.075)
    else:
        tax = (salary * 0.05)

    return tax

Also, I’m trying to learn so could you explain by putting #comments into the code :) Thank you!

Advertisement

Answer

1. Rewrite the code structure

First of all, I think most programmers do like to put function blocks all together and leave the main logic as clean/short as possible to improve readability. Therefore the ‘code structure’ like this could be hard to maintain or update in the future.

while True: #Loop the whole program
    from datetime import datetime, date #Get the Age of from user input
    
    def calculate_age(born): ...    
    def get_salary(): ...    
    def contribution(age): ...

    if __name__ == "__main__":
        # main logic
        ...

So this kind of structure is really weird, plus you have lots of variables (date_of_birth, age) declared between functions. Would be hard to do the update/maintenance. If I were you, I’d firstly revise the code like this way

from datetime import datetime, date #Get the Age of from user input
    
def calculate_age(born): ...    
def get_salary(): ...    
def contribution(age): ...

if __name__ == "__main__":  # It's as if the interpreter inserts this at the top of your module when run as the main program.
    program_continue = 'y'
    while program_continue.upper() in ['Y', 'YES']:
        print("Please enter your date of birth (dd mm yyyy)")
        date_of_birth = datetime.strptime(input("--->"), "%d %m %Y")
        age = calculate_age(date_of_birth)
        print("You are " ,int(age), " years old.")
        salary = get_salary() #get salary from get_salary()
        tax = contribution(age) #calculate the tax
        print("you have to pay", tax, " every month ")
        program_continue = str(input("Do you need to do another calculation? (y/n): "))
    print("Thank you for using this Calculator, Goodbye")

2. Introduce data structure? or class?

Honestly I don’t quite understand what do you mean by “using data structure”, so I guess make a “class” is the one you wish. Then you have to consider some points:

  • what should be the attributes for this class? dob, salary, anything else?
  • what will you expand in the future? name? gender? contact_info? handicapped or not?

Whatever, we just create a class with dob and salary for now.

class Person(object):
    def __init__(self, dob, salary):
        """
        input dob and salary only, age and tax will be calculated then
        """
        self.dob = dob
        self.salary = salary
        self.age = self.calculate_age() 
        self.tax = self.contribution()
    
    def calculate_age(self):
        today = date.today()
        return today.year - self.dob.year - ((today.month, today.day) < (self.dob.month, self.dob.day))

    def contribution(self):
        if self.age <= 35:
            tax = (self.salary * 0.20)
        elif 36 <= self.age <= 50:
            tax = (self.salary * 0.20)
        elif 51 <= self.age <= 55:
            tax = (self.salary * 0.185)
        elif 56 <= self.age <= 60:
            tax = (self.salary * 0.13)
        elif 61 <= self.age <= 65:
            tax = (self.salary * 0.075)
        else:
            tax = (self.salary * 0.05)
        return tax

So once you create a variable in the class Person, you can access the age, salary, tax via .age, .salary, .tax. Please notice that I did not put the function get_salary() into the class since it’s a function for “asking user’s salary” and has nothing to do with the attribute.

The main logic can be rewritten to:

if __name__ == "__main__":  # It's as if the interpreter inserts this at the top of your module when run as the main program.
    program_continue = 'y'
    while program_continue.upper() in ['Y', 'YES']:
        print("Please enter your date of birth (dd mm yyyy)")
        date_of_birth = datetime.strptime(input("--->"), "%d %m %Y")
        salary = get_salary()  #get salary from get_salary()
    
        ##### THESE ARE THE CHANGES START
        person_obj = Person(date_of_birth, salary)
        print("You are ", int(person_obj.age), " years old.")
        print("you have to pay", int(person_obj.tax), " every month ")
        ##### THESE ARE THE CHANGES END

        program_continue = str(input("Do you need to do another calculation? (y/n): "))
    print("Thank you for using this Calculator, Goodbye")

3. Future expansion

Let’s say if I want to add name as an attribute now. All I have to do is to modify the Person class. Should be easier for you to update in the future.

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement