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.