## function with loop and if statement help

This is the place for queries that don't fit in any of the other categories.

### function with loop and if statement help

Hi there, I just started working with python last week in to try and learn something new and I have encountered a problem.

The program I am trying to write is as follows
- asks the user how many books they bought
- asks the user the cost of each book
- if they buy 4 or more books, they receive a 40% discount on their purchase
-if they buy 3 books, they receive a 30% discount on their purchase
-if they buy 2 books, they receive a 20% discount on their purchase
-if they buy 1 book, they receive a 10% discount on their purchase
- must write the code using functions
-must call the function in from another module (using ECLIPSE IDE with pythonviewer)

My approach was to first find the total of the books using a for loop and then using if statements, i would apply the proper discount to the total to get the grand total. I have been able to run this code, but I cannot get the right answer if 4 books are purchased (discount doesnt apply properly) OR only one book is purchased (get error: local variable 'grand_total' referenced before assignment)

Here is my code:
Code: Select all
`def total_cost (numbooks):        total = 0            for numbooks in range(numbooks):        price_each_book = int(input("price of the book?"))        total = total + price_each_book                if numbooks >= 5:            grand_total = total - (total * 0.4)                elif numbooks == 4:            grand_total = total - (total * 0.4)            elif numbooks ==3:            grand_total = total - (total * 0.3)                elif numbooks ==2:            grand_total = total - (total * 0.2)                elif numbooks ==1:            grand_total = total - (total * 0.1)            return grand_total`

and to call and run the function from another module:

Code: Select all
`import maggiespizzanumbooks = int(input("How many books are you buying?"))s = maggiespizza.total_cost(numbooks)print ("total: {0} " .format(s))`

Any help would be appreciate, thanks for your time!
Tyreejackson

Posts: 7
Joined: Wed Jun 12, 2013 3:56 am

### Re: function with loop and if statement help

Code: Select all
`for numbooks in range(numbooks):`

Walk through your code one line at a time, be the interpreter, and you should be able to see what your program is doing, and compare that to what it should be doing. Especially what the line above is doing.
Join the #python-forum IRC channel on irc.freenode.net!

Please do not PM members regarding questions which are meant to be discussed publicly. The point of the forum is so that others can benefit from it. We don't want to help you over PMs or emails.

micseydel

Posts: 1916
Joined: Tue Feb 12, 2013 2:18 am
Location: Mountain View, CA

### Re: function with loop and if statement help

Well a lot of that stuff doesn't belong in the for loop. Calculate your total in the loop and then calculate your grandtotal outside it.

Also your if/elif statements are fairly unnecessary.
This is a good opportunity to use the min builtin.

Consider the following:
Code: Select all
`numbooks = int(input())discount = min(numbooks*0.1,0.4)print(discount)`

Here the discount is either the number of books times 0.1 or 0.4. Whichever is lower.

-Mek

Edit: Wah... I didn't even noticed he used the name twice in the for loop header.
• Use code tags when posting code.
• Include any errors with your post (in code tags).
• Make examples the minimum length to demonstrate your issue.

Mekire

Posts: 1362
Joined: Thu Feb 07, 2013 11:33 pm
Location: Tucson, Arizona

### Re: function with loop and if statement help

micseydel wrote:
Code: Select all
`for numbooks in range(numbooks):`

Walk through your code one line at a time, be the interpreter, and you should be able to see what your program is doing, and compare that to what it should be doing. Especially what the line above is doing.

Thanks for this. I switched the 'iterator' (I believe his is what it is called?) to "i" instead of numbooks, and this seemingly fixed all of my problems. The only reason that I used numbooks twice in the first place is because the IDE warned me that I had an unused variable, however, upon further reading it seems that an unused iterator is not a problem.
Tyreejackson

Posts: 7
Joined: Wed Jun 12, 2013 3:56 am

### Re: function with loop and if statement help

Mekire wrote:Well a lot of that stuff doesn't belong in the for loop. Calculate your total in the loop and then calculate your grandtotal outside it.

Also your if/elif statements are fairly unnecessary.
This is a good opportunity to use the min builtin.

Consider the following:
Code: Select all
`numbooks = int(input())discount = min(numbooks*0.1,0.4)print(discount)`

Here the discount is either the number of books times 0.1 or 0.4. Whichever is lower.

-Mek

Edit: Wah... I didn't even noticed he used the name twice in the for loop header.

I will look into this further, so i can code as efficiently as possible one day!! Not quite sure how to implement it as of now, though. Thank you for broadening my knowledge!
Tyreejackson

Posts: 7
Joined: Wed Jun 12, 2013 3:56 am

### Re: function with loop and if statement help

Congratulations on finding the solution. Switching the iterator will indeed solve your problem, but as I said you don't need to calculate the grand total inside the loop. You calculate the grand total for every single book but only actually need to do it after all books are input. It is a waste. Also as I said previously you really shouldn't be using if/elifs for every single option to figure out the discount rate. There is a much easier way.

Code: Select all
`def total_cost(numbooks):    total = 0    for i in range(numbooks):        price_each_book = float(input("price of the book?"))        total += price_each_book    discount = min(numbooks*0.1,0.4)    return total*(1-discount)`

Also you might want to consider putting some error checking on your inputs. As it stands the program will crash on a bad input.

-Mek
• Use code tags when posting code.
• Include any errors with your post (in code tags).
• Make examples the minimum length to demonstrate your issue.

Mekire

Posts: 1362
Joined: Thu Feb 07, 2013 11:33 pm
Location: Tucson, Arizona

### Re: function with loop and if statement help

Mekire wrote:Congratulations on finding the solution. Switching the iterator will indeed solve your problem, but as I said you don't need to calculate the grand total inside the loop. You calculate the grand total for every single book but only actually need to do it after all books are input. It is a waste. Also as I said previously you really shouldn't be using if/elifs for every single option to figure out the discount rate. There is a much easier way.

Code: Select all
`def total_cost(numbooks):    total = 0    for i in range(numbooks):        price_each_book = float(input("price of the book?"))        total += price_each_book    discount = min(numbooks*0.1,0.4)    return total*(1-discount)`

Also you might want to consider putting some error checking on your inputs. As it stands the program will crash on a bad input.

-Mek

Wow this is really elegant / efficient. It does all the work my program did but with half the code. I do have a question or two though if you don't mind...

The "+=" does what exactly? my guess would be is that it sums up the price_each_book variable at each stage of the loop? This is a lot more simple than writing total = total + price_each_book

From what I've read, the min() function returns the smallest item entered into the numbooks variable? I don't understand what the * 0.1,0.4 really does, although i do recognize them as the discount percentages. If you could shed any light on how i should be using this function it would be much appreciated! I will check back into this thread tomorrow!
Tyreejackson

Posts: 7
Joined: Wed Jun 12, 2013 3:56 am

### Re: function with loop and if statement help

Your discount is equal to the number of books times 0.1.
However the max discount is 0.4 so after you have 4 books it stays at 0.4.

The minimum builtin, min, returns the lowest of the values passed to it as arguments.
I pass it the arguments numbooks*0.1 and 0.4.
If numbooks*0.1 is lower than 0.4 it will return that value.
If numbooks*0.1 is greater than 0.4 it will return 0.4.

There is a builtin for finding maximums as well called max.

http://python-forum.org/viewtopic.php?f=6&t=4075#p4992

-Mek

Edit:
Just to be clear, there are two ways to pass arguments to min. You can pass it multiple arguments in which case it will return the lowest one; as in the following:
Code: Select all
`>>> min(3,4,6,2,7,0.25,200)0.25>>> `
Or you can pass it one argument which is a sequence (including generators); as in the following:
Code: Select all
`>>> mylist = [3,4,6,2,7,0.25,200]>>> min(mylist)0.25>>> `
• Use code tags when posting code.
• Include any errors with your post (in code tags).
• Make examples the minimum length to demonstrate your issue.

Mekire

Posts: 1362
Joined: Thu Feb 07, 2013 11:33 pm
Location: Tucson, Arizona

### Re: function with loop and if statement help

Mekire wrote:Your discount is equal to the number of books times 0.1.
However the max discount is 0.4 so after you have 4 books it stays at 0.4.

The minimum builtin, min, returns the lowest of the values passed to it as arguments.
I pass it the arguments numbooks*0.1 and 0.4.
If numbooks*0.1 is lower than 0.4 it will return that value.
If numbooks*0.1 is greater than 0.4 it will return 0.4.

There is a builtin for finding maximums as well called max.

http://python-forum.org/viewtopic.php?f=6&t=4075#p4992

-Mek

Edit:
Just to be clear, there are two ways to pass arguments to min. You can pass it multiple arguments in which case it will return the lowest one; as in the following:
Code: Select all
`>>> min(3,4,6,2,7,0.25,200)0.25>>> `
Or you can pass it one argument which is a sequence (including generators); as in the following:
Code: Select all
`>>> mylist = [3,4,6,2,7,0.25,200]>>> min(mylist)0.25>>> `

Thanks Mekire. Your explanation is extremely helpful. I will try to use the min builtin next time when the opportunity arises!
Tyreejackson

Posts: 7
Joined: Wed Jun 12, 2013 3:56 am