Hello, I'm very new to python but made this as a sort of exercise. It is a loan calculator that takes into account user input.

r = input('What is your interest rate?   ')
t = input('How many payments will you make?   ')
la = input('What was the amount of the loan?   ')
rt = raw_input('Do you make your payments weekly, monthly, quarterly, or annually?   ')

r = r + .0

r = r / 100

rr = r / 52
x = (1.0 + rr) ** t
y = rr / (x - 1.0)
isloanweek = (rr + y) * la

rr = r / 12
x = (1.0 + rr) ** t
y = rr / (x - 1.0)
isloanmonth = (rr + y) * la

rr = r / 4
x = (1.0 + rr) ** t
y = rr / (x - 1.0)
isloanquarter = (rr + y) * la

rr = r / 1
x = (1.0 + rr) ** t
y = rr / (x - 1.0)
isloanannual = (rr + y) * la

whatloan = True
while whatloan:
    if rt == 'weekly':
        print isloanweek
        whatloan = False
    elif rt == 'monthly':
        print isloanmonth
        whatloan = False
    elif rt == 'quarterly':
        print isloanquarter
        whatloan = False
    elif rt == 'annually':
        print isloanannual
        whatloan = False
    else:
        rt = raw_input('Sorry that was not an option, please respond with weekly, monthly, quarterly, or annually:   ')

Note:
I moved this post to its own thread. As you look at the code there are many lines of repetitious code, a sign that a function is due. Can anybody help Mensa180 in a nice way to improve the Python coding style?

Mensa180, thanks for the code contribution!

Recommended Answers

All 11 Replies

Mensa: your code was very well structured and a nice example of reading user input then using it for calculation. Here's how I've modified your code:

def calc_payment(int_rate, num_pmnts, principal, freq):
    ''' This function will calculate the payment amount of a loan.
    @ Inputs
    - int_rate  - The interest rate of the loan
    - num_pmnts - The number of payments required
    - principal - The original amount of the loan (minus down-payment)
    - freq      - Frequency of payments (weekly, monthly, quarterly, annually)
    
    @ Returns
    - pmnt_amt  - The amount that each payment will be
    '''
    
    freq_lookup = {'weekly':52, 'monthly':12, 'quarterly':4, 'annually':1}
    int_rate = float(int_rate) / 100
    
    rr = int_rate / freq_lookup[freq]
    x = (1.0 + rr) ** num_pmnts
    y = rr / (x - 1.0)
    pmnt_amt = (rr + y) * principal
    
    return pmnt_amt


def main():
    r = input('What is your interest rate?   ')
    t = input('How many payments will you make?   ')
    la = input('What was the amount of the loan?   ')
    rt = None
    while rt not in ['weekly', 'monthly', 'quarterly', 'annually']:
        if rt:
            rt = raw_input('Sorry that was not an option, please respond with weekly, monthly, quarterly, or annually:   ').lower()
        else:
            rt = raw_input('Do you make your payments weekly, monthly, quarterly, or annually?   ').lower()
    payment = calc_payment(r, t, la, rt)
    print 'Your %s payment will be %.2f' % (rt, payment)


if __name__ == '__main__':
    main()
    raw_input('Press Enter to Exit...')

Here are the modifications I made:

1. Moved the payment calculation to a function called calc_payment and added comments explaining what the function does, what inputs it expects and what the output means (this is something that you should get in the habit of doing, as it will help in the future and is good coding practice).

2. I removed the r = r + .0 line and instead consolidated it with the line immediately below it using the built-in float function (which converts the number to floating point, as does adding .0).

3. I added a dictionary lookup for the payment frequency. Each key is the word description that you ask the user for (weekly, monthly, quarterly, annually) and then the value corresponding to each key is the frequency that you were using in the calculations (52, 12, 4, 1 respectively). This allows us to use one calculation instead of doing four and then picking one of the results later.

4. Moved the user input requesting into the "main" function. Also added a statement that you'll see quite frequently when working with Python: if __name__ == '__main__': . This is typically the only statement that is not inside of a function (aside from a main function call or some initialization stuff, which are inside this "if" block). This statement makes sure that the program is running as the 'main' script, and executes accordingly. So now, if another program were to input <script_name> where script_name is the name of this script, that other program would not automatically run the main function and ask the user for input. Then your 'main' program would be able to call <script_name>.calc_payment and make use of it however you'd like.

5. Moved the part that tells the user they provided an incorrect input for frequency to where we get the input. This makes sure we don't do the calculation until the user has given us a correct input. I also used lower to make sure the string is all lower case and a list to validate and make sure their input is kosher.

I think that's about it, but if you have any questions about my modifications, please feel free to ask for further details!

commented: nice info +9

Mensa: your code was very well structured and a nice example of reading user input then using it for calculation. Here's how I've modified your code:

def calc_payment(int_rate, num_pmnts, principal, freq):
    ''' This function will calculate the payment amount of a loan.
    @ Inputs
    - int_rate  - The interest rate of the loan
    - num_pmnts - The number of payments required
    - principal - The original amount of the loan (minus down-payment)
    - freq      - Frequency of payments (weekly, monthly, quarterly, annually)
    
    @ Returns
    - pmnt_amt  - The amount that each payment will be
    '''
    
    freq_lookup = {'weekly':52, 'monthly':12, 'quarterly':4, 'annually':1}
    int_rate = float(int_rate) / 100
    
    rr = int_rate / freq_lookup[freq]
    x = (1.0 + rr) ** num_pmnts
    y = rr / (x - 1.0)
    pmnt_amt = (rr + y) * principal
    
    return pmnt_amt


def main():
    r = input('What is your interest rate?   ')
    t = input('How many payments will you make?   ')
    la = input('What was the amount of the loan?   ')
    rt = None
    while rt not in ['weekly', 'monthly', 'quarterly', 'annually']:
        if rt:
            rt = raw_input('Sorry that was not an option, please respond with weekly, monthly, quarterly, or annually:   ').lower()
        else:
            rt = raw_input('Do you make your payments weekly, monthly, quarterly, or annually?   ').lower()
    payment = calc_payment(r, t, la, rt)
    print 'Your %s payment will be %.2f' % (rt, payment)


if __name__ == '__main__':
    main()
    raw_input('Press Enter to Exit...')

Here are the modifications I made:

1. Moved the payment calculation to a function called calc_payment and added comments explaining what the function does, what inputs it expects and what the output means (this is something that you should get in the habit of doing, as it will help in the future and is good coding practice).

2. I removed the r = r + .0 line and instead consolidated it with the line immediately below it using the built-in float function (which converts the number to floating point, as does adding .0).

3. I added a dictionary lookup for the payment frequency. Each key is the word description that you ask the user for (weekly, monthly, quarterly, annually) and then the value corresponding to each key is the frequency that you were using in the calculations (52, 12, 4, 1 respectively). This allows us to use one calculation instead of doing four and then picking one of the results later.

4. Moved the user input requesting into the "main" function. Also added a statement that you'll see quite frequently when working with Python: if __name__ == '__main__': . This is typically the only statement that is not inside of a function (aside from a main function call or some initialization stuff, which are inside this "if" block). This statement makes sure that the program is running as the 'main' script, and executes accordingly. So now, if another program were to input <script_name> where script_name is the name of this script, that other program would not automatically run the main function and ask the user for input. Then your 'main' program would be able to call <script_name>.calc_payment and make use of it however you'd like.

5. Moved the part that tells the user they provided an incorrect input for frequency to where we get the input. This makes sure we don't do the calculation until the user has given us a correct input. I also used lower to make sure the string is all lower case and a list to validate and make sure their input is kosher.

I think that's about it, but if you have any questions about my modifications, please feel free to ask for further details!

Thanks! I got into Python just recently when I saw projecteuler.net and thought I'd give it a shot. I've only just messed with C and Java but Python seems easier for me to get the syntax of at first. Seeing an explanation and example of how my code could be made to be smoother is really helpful, thanks again!

OK I have a small question. What do %s and %.2f stand for? It looks like %s stands for freq and %.2f is the amount given by calc_payment(...).

Also I'm still trying to grasp the _name_ ==' _main_': concept.

Other than that I pretty much understand what you did! Not bad for a 17 year old!? Now I just need to think of another exercise where I can experiment in defining and using functions.

If you are familiar with C and its printf() function then you can use %s for strings and %0.2f for floats with 2 decimals. In Python like in Ruby you can use %s also for unformatted numbers.

In Ruby (much like C):

printf( "Number: %5.2f, String: %s\n", 1.23456, "hello" )
printf( "Number: %s, String: %s\n", 1.23456, "hello" )

In Python:

print( "Number: %5.2f, String: %s\n" % ( 1.23456, "hello" ) )
print( "Number: %s, String: %s\n" % ( 1.23456, "hello" ) )

In either case the output is:

Number:  1.23, String: hello
Number: 1.23456, String: hello

Doh! I get it now, thanks, I missed the end of the line where it specified where it got the vars from. That explains why it didn't make sense to me. print 'Your %s payment will be %.2f' % (rt, payment)

Just keep asking, we are all more than willing to help a sprouting Python talent.

Just upgraded to Python 3.1.1, I think I was using 2.6. Apparently you now have to use parenthesis instead of just telling it what you want to print. print 'Hello Python' vs print ('Hello Python') I'm not sure what they've done with raw_input() , does plain old input() have the same functionality now? I will have to google the changes.

For now I am trying to figure out how to use functions with one another effectively.

def mpg():
    travel = input('How many miles have you traveled?   ')
    gallons = input('How many gallons of fuel did you use?   ')
    mpg = float(travel) / float(gallons)
    print ('You get', mpg, 'miles per gallon.')

def mpt():
    mpg = input('How many miles per gallon does your vehicle get?   ')
    tanksize = input('How large is your gas tank?   ')
    tankmiles = float(tanksize) * float(mpg)
    print ('You will get', tankmiles, 'miles on a tank of fuel.' )

For example I am trying to use mpt(mpg()) to determine miles per tank without the user knowing at first what their mpg is. I have been on the road for most the day so I have not yet had a chance to research how to do things like this more thoroughly.

Thanks! I am on the road and thus without internet for long periods of time so sometimes I just have to sit frustrated wondering why a bit of code won't work now when it did before :).

I'm not sure why this keeps giving me "Guess again!" though. Even though it is simple addition I made it print the answer to make sure there was no possibility of me getting it wrong, it worked in 2.6 and I thought the logic was fairly straightforward.

from random import randint
a = randint (1,10,)
b = randint (1,10,)
z = a + b
print (z)
print (a, "+", b, "=")

y = input('What is the answer?   ')

control = True
 
while control:
    if  y == z:
        print ('Correct!')
        control = False
    while y != z:
        y = input('Guess again!   ')

I read through that doc and tried changing input() to eval(input()) but that just gave me parsing errors.

I hope this is one of those things I can come back to in 20 minutes and catch immediately, but so far I'm still looking.

>>> from random import randint
>>> a = randint (1,10,)
>>> a
2
>>> b = randint (1,10,)
>>> b
5
>>> z = a + b
>>> z
7
>>> print (a, "+", b, "=")
2 + 5 =
>>> y = input('What is the answer?   ')
What is the answer?   7
>>> y
'7'
>>> #You see now that y is a string
>>> type(y)
<class 'str'>
>>> control = True
>>> control
True
>>> while control:
    if  int(y) == z:
        print ('Correct!')
        control = False
    while int(y) != z:
        y = input('Guess again!   ')

        
Correct!
>>> z = 2
>>> while control:
    if  int(y) == z:
        print ('Correct!')
        control = False
    while int(y) != z:
        y = input('Guess again!   ')

        
>>> #you see it not work if no  "y == z"

Try this.

from random import randint
a = randint (1,10,)
b = randint (1,10,)
z = a + b
print (z)
print (a, "+", b, "=")

while True:
    y = input('What is the answer?   ')
    if z == int(y):
        print ('Correct!')
        break
    else:
        print('try again')

That was it, thanks.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.