Your naming is a bit unPythonic. Most variable and function names should be snake_case, so tuitionIncrease
should be tuition_increase
. But constants should be UPPER_SNAKE_CASE, meaning inState
is IN_STATE
. You should also use clear names even if they're briefly used. i
for input isn't great, as i
is often used in for
loops. Instead, you could use something like residency
, that matches what the value means.
Speaking of those constants, you should actually put the three of them into a dictionary instead. A dictionary takes a string as a key and returns and associated value. So you can cut out the middle man and pass the user's input into the dictionary to get the number you need.
RESIDENCY_COST = {
"I": 10000,
"O": 24000,
"G": 40000,
}
About that input. You don't handle cases where the user enters input wrong, or if they enter a valid letter but as lowercase. Luckily we can do both of these easily. For avoiding the lowercase problem, use the str.upper()
method. It turns all charactes in a string into uppercase so even if someone enters 'i' you'll change it to 'I'.
The way you can handle invalid input is by trying to get the value from the dictionary from above. You access values in a dictionary with the syntax dictionary[key]
and you can write code so that you attempt to pass a key and if the key doesn't exist Python handles it. Here's how it would look:
residency = raw_input('Please input your type of residency, I for in-state, O for out-of-state, and G for graduate: ')
try:
cost_of_tuition = RESIDENCY_COST[residency.upper()]
except KeyError:
print ('Please enter I, G or O ONLY.')
But that's no good, that means we tell the user what to do and they don't get a second attempt. That's why you can wrap the whole thing in an infinite while
loop and break it when you get valid input.
while True:
residency = raw_input('Please input your type of residency, I for in-state, O for out-of-state, and G for graduate: ')
try:
cost_of_tuition = RESIDENCY_COST[residency]
break
except KeyError:
print ('Please enter I, G or O ONLY.')
This will keep running the code in the while
block forever until it reaches the break
command. It can only reach there after a correct key is entered and cost_of_tuition
has been set.
Instead of using this while x != 5
, you can use a simple for
loop.
for x in range(5):
Though since you don't need x
, it's Python style to instead say for _ in range(5)
to show that _
isn't a value you're actually using.
This block of calculation is a little unclear. What does intMath
and fnlMath
mean? Clearer names about the purpose and context of the values makes code infinitely more readable.
intMath = costOfTuition * 0.03
tuitionIncrease.append(intMath)
fnlMath = intMath + costOfTuition
years.append(fnlMath)
costOfTuition = fnlMath
Also, have a loop where you append to lists, but then you manually read both those lists to create sets of 5 very similar values that should be lists. Why not make these directly in your loop? I'd change the loop block to this:
intMath = cost_of_tuition * 0.03
tuition_increase.append("${:,.2f}".format(intMath))
fnlMath = intMath + costOfTuition
academic_years.append("${:,.2f}".format(fnlMath))
cost_of_tuition = fnlMath
Of course you need the sum too, but instead of using sum
, just create the sum in the for loop you're already doing.
total_tuition_increase += intMath
tuition_increase.append("${:,.2f}".format(intMath))
You still need to format it, but you can do that within the print command:
print('TOTAL TUITION INCREASE ${:,.2f}'.format(total_tuition_increase))
You seem to have misunderstood format
. It's not intended primarily to be a variable converter, it's actually mainly for inserting values into strings, as I showed above. It has other handy features too, like specifying column widths so that spaces match up. So you could print one of your results like this instead:
print('2016-17 {:>10} {:>10}'.format(academic_years[0], tuition_increase[0]))
The 10
tells Python to use 10 spaces regardless of how long the string is, and the >
makes it right justified. This will make it neater to read. I also think that since you have actual lists now, you could loop over them instead. You can use zip
to attach 2 lists together and that way iterate over both at once. You will also need to loop over the year to achieve this (otherwise you'd print the same year every time). You can do that using a BASE_YEAR
constant and using enumerate
to see what iteration you're on.
Here's how the loop would look:
BASE_YEAR = 16
for i, (tuition, increase) in enumerate(zip(academic_years, tuition_increase)):
print('20{}-{} {:>10} {:>10}'.format(i + BASE_YEAR, i + 1 + BASE_YEAR, tuition, increase))