0
\$\begingroup\$

I've just started coding and have written a program to calculate your tax to be paid. Is there anywhere where I can improve this?

while True:
    try:

      income = int(input("Please enter your taxable income: "))
  except ValueError:
      print("Sorry, I didn't understand that please enter taxable income as a number")

      continue
  else:


      break
  if income <= 18200:
      tax = 0

  elif income <= 37000: 
      tax = (income - 18200) * 0.19 

  elif income <= 90000:
      tax = (income-37000) * 0.235 + 3572 

  elif income <= 180000:
      tax = (income - 90000) * 0.37 + 20797 

  else:
      tax = (income - 180000) * 0.45 + 54097

  print("you owe", tax, "dollars in tax!" )
New contributor
AMG_ is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
\$\endgroup\$

put on hold as off-topic by Graipher, Mast, l0b0, IEatBagels, Peilonrayz Aug 14 at 15:51

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Code not implemented or not working as intended: Code Review is a community where programmers peer-review your working code to address issues such as security, maintainability, performance, and scalability. We require that the code be working correctly, to the best of the author's knowledge, before proceeding with a review." – Graipher, Mast, l0b0, IEatBagels, Peilonrayz
If this question can be reworded to fit the rules in the help center, please edit the question.

  • 2
    \$\begingroup\$ identation isnt proper \$\endgroup\$ – Lalit Verma Aug 14 at 7:35
  • 1
    \$\begingroup\$ @LalitVerma At first I thought the try line was just indented too far, but actually all the rest of the code is at the wrong level... \$\endgroup\$ – Graipher Aug 14 at 7:54
  • 1
    \$\begingroup\$ To properly indent your code: remove the current code, paste your original code, select your freshly-pasted code and hit Ctrl+K. Or use an editor to give every line of code 4 extra spaces, that does the same thing. Considering indentation is very important in Python, you'll have to fix it to comply with our help center (which requires code to work). \$\endgroup\$ – Mast Aug 14 at 8:35
  • \$\begingroup\$ AFAICT that's not working code, even if indented properly. The code after the try block can't be executed, because it'll either break or continue before reaching it. \$\endgroup\$ – l0b0 Aug 14 at 8:48
  • 1
    \$\begingroup\$ That depends on how wrong the indentation is. If the rest of the code is supposed to be outside the while loop it would work. \$\endgroup\$ – Graipher Aug 14 at 8:53
3
\$\begingroup\$

Given the bad indentation of the original code, I will assume you meant to post code that looks like this

while True:
    try:

        income = int(input("Please enter your taxable income: "))
    except ValueError:
        print("Sorry, I didn't understand that please enter taxable income as a number")

        continue
    else:
        break

if income <= 18200:
    tax = 0

elif income <= 37000: 
    tax = (income - 18200) * 0.19 

elif income <= 90000:
    tax = (income-37000) * 0.235 + 3572 

elif income <= 180000:
    tax = (income - 90000) * 0.37 + 20797 

else:
    tax = (income - 180000) * 0.45 + 54097

print("you owe", tax, "dollars in tax!" )

I would suggest you use an IDE or a linter, both of which will point out syntax problems in the code.


The idea behind the code can be summarized as

Get the income from user input
Calculate the tax
Print the amount owed

This is a good structure to have. You have three clear boundaries and have split the work appropriately. You can make this explicit with well named functions. I would lay it out like this

def get_income():
    while True:
        try:

            income = int(input("Please enter your taxable income: "))
        except ValueError:
            print("Sorry, I didn't understand that please enter taxable income as a number")

            continue
        else:
            break

    return income


def compute_tax(income):
    if income <= 18200:
        tax = 0
    elif income <= 37000: 
        tax = (income - 18200) * 0.19 
    elif income <= 90000:
        tax = (income - 37000) * 0.235 + 3572 
    elif income <= 180000:
        tax = (income - 90000) * 0.37 + 20797 
    else:
        tax = (income - 180000) * 0.45 + 54097

    return tax


if __name__ == "__main__":
    income = get_income()
    tax = compute_tax(income)
    print("you owe", tax, "dollars in tax!")

The advantage of this is that your code for working out how much tax is owed is easy to use in another python module.

# tax_credits.py
from tax import compute_tax
...

If we look at how the tax is computed, the pattern is very clear. At each tax bracket we subtract an amount, multiply by a percentage, and add back an amount

tax = (income - S) * P + A

We could change the code to first figure out the tax bracket the income falls into, then compute the tax amount. While this doesn't look any better now, it will be beneficial to explore this path.

def compute_tax(income):
    if income <= 18200:
        S, P, A = 0, 0, 0  # Values picked so the tax amount is always 0. 
    elif income <= 37000: 
        S, P, A = 18200, 0.19, 0
    elif income <= 90000:
        S, P, A = 37000, 0.235, 3572 
    elif income <= 180000:
        S, P, A = 90000, 0.37, 20797 
    else:
        S, P, A = 180000, 0.45, 54097

    tax = (income - S) * P + A
    return tax

Since this repeated code now looks a bit easier to manager, let's turn it into a loop. I'll leave the details out as there are a few features of python that might be new to you, and are worth looking up yourself.

def compute_tax(income):
    # (C,      P,       A)
    # (cutoff, percent, additive)
    # S is reused from the previous iteration of the loop
    # so no need to store it.
    tax_brackets = (
        (18200, 0, 0), (37000, 0.19, 0), (90000, 0.235, 3572), (180000, 0.37, 20797)
    )
    # The final bracket, use if the income is bigger than any cutoff
    last_bracket = (None, 0.45, 54097)
    previous_cutoff = 0
    for cutoff, percent, additive in tax_brackets:
        if income <= cutoff:
            break
        previous_cutoff = cutoff
    else:
        # If we get here we never found a bracket to stop in
        _, percent, additive = last_bracket

    tax = (income - previous_cutoff) * percent + additive
    return tax

We should probably include some sanity checks incase somebody incorrectly changes values. As an example, we could check each cutoff is bigger than the last.

Note that this code is a bit denser than the original, and I don't know if I would recommend using a loop. If the original code ever gets more complex this is how I would try and simplify it. But until then I would leave the explicit if/elif/else statements in previous suggestion.


def get_income():
    while True:
        try:

            income = int(input("Please enter your taxable income: "))
        except ValueError:
            print("Sorry, I didn't understand that please enter taxable income as a number")

            continue
        else:
            break

    return income

The logic here is pretty solid. I would be hesitant to change to much. The only thing I do not like is int, as it is perfectly reasonable to earn a fractional unit of the currency.

There are a lot of ways you could code this sort of function. Here is one alternative that removes a few unnecessary parts.

def get_income():
    while True:
        try:
            return float(input("Please enter your taxable income: "))
        except ValueError:
            print("Sorry, I didn't understand that please enter taxable income as a number")
\$\endgroup\$
  • \$\begingroup\$ wow thanks for that, I definitely have alot to learn \$\endgroup\$ – AMG_ Aug 14 at 14:45
2
\$\begingroup\$

Hello @AMG_ and welcome to codereview.

One good thing here is checking that the user input is a number. It's a good habit to always assume user input is broken, and give them an indication of what's going wrong. You can also do other validation at this stage. What should happen if, for example, they enter a negative number? By the way, although python does support try...except...else the else is a bit of a niche feature. It's more common, and hence easier for python programmers to see that it's correct, if you put the break at the end of the try section.

One cause for concern is the magic numbers in this code. If, say the government changed the 0.19 threshold from 37k to 38k, you'd need to remember to change the 37000 in both its own band and the 90000 band. Moreover, because I know the idea behind marginal tax rates, I know what 20797 is meant to refer to. Even though I'm aware of it now I'm not checking whether the calculation is accurate. If the government changed the 37000 tax band, all those numbers would need to change and it would be terribly easy to miss one.

This code would be more maintainable if there were a list of thresholds all in one place, and the contribution from lower tax bands were calculated by the code rather than hard coded.

I would split the bit of code which calculates the tax into a function. It's generally considered good practice to split code which does user interaction (display and keyboard parsing) away from code which does calculations. The behaviour would be the same, but it's much easier to follow what's going on.

\$\endgroup\$
  • \$\begingroup\$ Hi, thanks for that. I am just learning so could you talk me through how i could change it to have thresholds? and the splitting also? \$\endgroup\$ – AMG_ Aug 14 at 13:45

Not the answer you're looking for? Browse other questions tagged or ask your own question.