Not understanding why this won't sum up properly - python

grades = [100, 100, 90, 40, 80, 100, 85, 70, 90, 65, 90, 85, 50.5]
def grades_sum(grades):
sum = 0
for i in grades:
sum += grades[i]
print(grades_sum(grades))
That's my code and I'm trying to understand why I'm getting an out of index traceback.

Iterating over a list will return the item in the list, not the index of the item. The correct code as you have written it would look like this:
def grades_sum(grades):
total = 0
for grade in grades:
total += grade
return total
Of course as others have answered this can be done much more elegant using sum.
If you actually need the index for something else you could use enumerate like this:
def grades_sum(grades):
total = 0
for i, grade in enumerate(grades):
total += grade #or grades[i]
return total
Or if you don't care about retrieving the item at all
def grades_sum(grades):
total = 0
for i in range(len(grades)):
total += grades[i]
return total

You don't need to do grade[i] because you're already referencing the elements in the list - all you need to do it replace that with a plain old i
However, there is already a builtin function for this - sum
print(sum(grades))

for i in grades: iterates over the elements in grades. It doesn't iterate over the indexes.
To fix your code, just use i instead of grades[i].
Don't be afraid of using print statements. They're excellent for debugging code.

Related

I want make this(sum) as a list form in python [duplicate]

This question already has answers here:
number of values in a list greater than a certain number
(9 answers)
Closed 5 years ago.
marks = [90, 25, 67, 45, 80]
a = marks
print(marks.count(a>=60))
I want to see how many students got marks over 60
You could do this:
In [6]: sum(x >= 60 for x in marks)
Out[6]: 3
You can use filter to include only the marks you care about:
marks = [90, 25, 67, 45, 80]
print(len(filter(lambda x: x>=60, marks)))
How many scores over 60?
>>> marks = [90, 25, 67, 45, 80]
>>> len([score for score in marks if score > 60])
3
This uses a list comprehension to create a new list containing only those scores over 60, then the length of the new list tells you have many scores there are above 60.
Another common way is to use sum():
>>> sum(1 if score > 60 else 0 for score in marks)
3
You can also take advantage of the fact that booleans are ints:
>>> sum(score > 60 for score in marks)
3
Or, to better your understanding, using a for loop:
count = 0
for score in marks:
if score > 60:
count += 1
print count
I hope this one can be helpful too.
Here we are using filter function for getting elements greater or equal to 60 and then using len function to get no. of elements.
Try this code snippet here
marks = [90, 25, 67, 45, 80]
print(len(filter(lambda x: x>=60,marks)))

<type 'NoneType'> issue when doing math

I have the following code, but when i run it I get type 'NoneType'. I pinpointed to my "summation" variable being the one that has Nonetype, why is that? and how can i change it? I tried making into a float() but it did not work for me. Any insights would be welcome.
grades = [100, 100, 90, 40, 80, 100, 85, 70, 90, 65, 90, 85, 50.5]
def grades_sum(scores):
total = 0
for item in scores:
total = item + total
print total
grades_sum(grades)
def grade_average(grades):
summation = grades_sum(grades)
average = summation / float(len(grades))
return average
print grade_average(grades)
Change the print to a return.
def grades_sum(scores):
total = 0
for item in scores:
total = item + total
return total
Well summation just calls the function, nothing else, so it is equal to a NoneType or basically nothing. Change print total to return total to allow summation to be equal to whatever total is.
def grades_sum(scores):
total = 0
for item in scores:
total = item + total
return total
When you define grades_sum(), you don't return anything, you just print it. Change it to this:
def grades_sum(scores):
total = 0
for item in scores:
total = item + total
print total
return total

Python while looping over list but not finding value

I have a while loop that is looping over a list trying to find the number 1. I have the code below and it loops over "almost" all the list but it does not find the index for value 1
numbers = [24, 10, 92, 28, 71, 1, 80, 70]
counter = 0
number_to_find = 1
def my_loop():
global counter
while counter > 6: #Also not sure while 7 doesn't work, says out of range?
if numbers[counter] == number_to_find:
print "Number found at position", counter
else:
print "Counter not found in position" , counter
counter = counter + 1
my_loop()
print my_loop()
This is a very confusing bit of code.
You print the output, but the function does not return anything. (It also prints things, but it does not return anything.)
The function has a while loop and also recurs upon itself. (There are some cases where this is appropriate, but this is not one of them.)
counter is initially 0, but your first check is if counter > 6. 0 is not greater than six. (This is not technically wrong, but very confusing.)
The value 1 is at index 5. Why are you looking for 6?
Once you have reached the desired index, you do not terminate the loop.
You can achieve what you're looking for using the following piece of code:
numbers = [24, 10, 92, 28, 71, 1, 80, 1, 70]
number_to_find = 1
for i,j in enumerate(numbers):
if j == number_to_find:
print i, "=>", j
# Output
>>> 5 => 1
>>> 7 => 1
If your numbers doesn't contains repeated numbers, you can use the following piece of code, as sugested by kojiro:
numbers = [24, 10, 92, 28, 71, 1, 80, 70]
number_to_find = 1
print numbers.index(number_to_find)
# Output
>>> 5
But if your code contains repeated chars, it'll show only the first ocurrence:
numbers = [24, 10, 92, 28, 71, 1, 80, 1, 70]
number_to_find = 1
print numbers.index(number_to_find)
# Output
>>> 5
while counter > 6:
If counter is greater than 6, it must be 7 or greater. If you're looping while counter > 7, you're indexing out of the range of the size of the list (which is indexed from 0 to 7).
global counter
Don't do this. You shouldn't use globals. There are good reasons
def my_loop():
...
my_loop()
You don't need recursion for this. This is quite simple with just a for loop (in fact, you can do it without that).
I'll post a few ways to solve this problem:
enumerate
def find_needle(needle, haystack):
for idx, item in enumerate(haystack):
if needle == item:
return idx
return None
index
def find_needle(needle, haystack):
return haystack.index(needle)
These two implementations don't do exactly the same thing - the first will return None if needle isn't found in haystack, where the second will throw a ValueError. I think the former is more forgiving, but it's up to you.
So there are many ways to do this, iteratively and recursively but to take the OP's code as is and what I think they were attempting.
Note: it is generally considered bad practice to use global variables, you should pass the list of numbers and the number to find to the function.
Note: your while loop is effectively implementing a for loop - for counter in range(len(numbers)): would provide the same result
numbers = [24, 10, 92, 28, 71, 1, 80, 70]
number_to_find = 1
def my_loop():
counter = 0
while counter < len(numbers):
if numbers[counter] == number_to_find:
print "Number found at position", counter
else:
print "Counter not found in position" , counter
counter = counter + 1
my_loop()
Output:
Counter not found in position 0
Counter not found in position 1
Counter not found in position 2
Counter not found in position 3
Counter not found in position 4
Number found at position 5
Counter not found in position 6
Counter not found in position 7
Doing the same thing with a for loop:
for counter in range(len(numbers)):
if numbers[counter] == number_to_find:
print "Number found at position", counter
else:
print "Counter not found in position" , counter
Would output the same.
However, perhaps a more idiomatic approach for Python would be to use enumerate:
for counter, number in enumerate(numbers):
if number == number_to_find:
print "Number found at position", counter
else:
print "Counter not found in position" , counter
To find first occurence use numbers.index(x) where x is the number you are searching or for all of them indices = [idx for idx, number in enumerate(numbers) if elem_list == x]
For starters, I think you mean for your else block to correspond to the if. Right now it's associated with the while. Indent the else so it's aligned with the if, and then indent the three lines after the else to align with the print after the if:
if numbers[counter] == number_to_find:
print "Number found at position", counter
else:
print "Counter not found in position" , counter
counter = counter + 1
my_loop()
Once you fix that, your second problem will be that your program will exit immediately because your while condition evaluates to 0 > 6, which is false, so the if block will never even run. Minimally you'll want to change the > to <. At that point, your code will mostly work like you expect it to, but consider:
The application will go into an infinite loop once it finds the value it's looking for.
A for loop would be much nicer than a while with a counter.
You should really avoid using global variables if at all possible (it's very possible here).

How do I print out the sum of a list given certain constraints

I'm trying to print the sum of a list generated through raw_input.
The numbers in the list must be between 1 and 1000, inclusive. The length of the list must be below 1000.
here is my code thus far:
initial_list = raw_input()
integer= initial_list.split(' ')
if len(integer) <= 1000:
for i in integer:
if i >= 1 and i<=1000:
actual_integer = map( int, integer)
print sum(actual_integer)
This does not print anything. Any suggestions and/or alternatives?
If I understand your objective correctly, you've got all the right ideas, you just need to re-order your logic a little and make sure you are clear in your head about when you're dealing with a list of values and when you're dealing with a single value.
You may wish to consider your variable naming, too, as good names can help you keep track of whether the variable has a type with multiple values or single values. I've updated your code with that in mind
initial_list = raw_input().split() # split(' ') works, but you don't actually need the ' ',
# split() on its own does the same job here
if len(initial_list) <= 1000:
actual_integers = map(int, initial_list) #Moved to here. Note that
#actual_integers is a list
#so for the following comparison
#you just want to look at the max
#and min (individual values)
if min(actual_integers) >= 1 and max(actual_integers) <= 1000:
print sum(actual_integers)
else: #Just added two nice messages to the user if it doesn't print out.
print 'integers must be in range 1-1000 inclusive'
else:
print 'your list must have 1000 integers or fewer'
This code here does what you need but there is no error checking.
initial_list = raw_input() # there should be some prompt text
# no error checking
integer = initial_list.split(' ')
# no output for lists > 1000
if len(integer) <= 1000:
print sum(filter(lambda i: 0 < i <= 1000, map(int, integer)))
The output
$ python test.py
1 2 3 1500 0
6
If I understand your question correctly, this maybe what you're looking for.
This code will prompt the input and append the input to the list lst until lst will have 1000 elements. It will only take an input if the input is a number between 1 and 1000 and it will give you the sum after every input.
lst = []
while len(lst) <= 999:
initial_list = raw_input('Input numbers between 1 and 1000:')
if initial_list.isdigit() and int(initial_list) <= 1000 and int(initial_list) >= 1:
lst.append(int(initial_list))
print 'List:', lst #prints the list
total = sum(lst)
print 'List Sum:', total #prints the list sum
else:
print 'Input must be numbers between 1 and 1000'
Output:
Input numbers between 1 and 1000:12
List: [12]
List Sum: 12
Input numbers between 1 and 1000:45
List: [12, 45]
List Sum: 57
Input numbers between 1 and 1000:156
List: [12, 45, 156]
List Sum: 213
Input numbers between 1 and 1000:256
List: [12, 45, 156, 256]
List Sum: 469
Input numbers between 1 and 1000:

Working with empty lists

Okay so I am trying to create an empty list, then add integers to the list to then pick out the highest,lowest and 5 middle numbers( in descending order using a slice) and put them on display... seems simple enough....
def main():
nums = []
for i in range(20,80,9):
nums.append(i)
print(*nums,sep=' ')
print('The highest number is',max(nums))
print('The lowest number is',min(nums))
print('The middle 5 sorted high to low:')
nums.sort()
nums.reverse()
print (*nums[1:6])
main()
Okay so i edited it using your suggestions and the program works fine..... I just cant wrap my head around that damned while loop.... Can anyone see how I could integrate that?
while nums.append(i):. list.append returns None, and None does not evaluate to true. So your print statements will never be executed.
nums.reverse[2:6] reverse is a method and reverses the list in place. It does not return anything. So this part will throw a TypeError. You want to instead call nums.reverse()
The reverse method does not sort. You need nums.sort()
nums[2:6] will get you the elements from index 2 to 6 (exclusive). So this will only get you 4 elements. Additionally, your list has 9 elements (7 if you exclude the min and max). The middle 5 elements would not be between index 2 and 6.
Python has a help() function, use it if you need to know what functions/methods return.
You could refactor your code to use a while loop like so.
def main():
nums = []
i = 20
while i < 80:
nums.append(i)
print(*nums,sep=' ')
i += 9
print('The highest number is',max(nums))
print('The lowest number is',min(nums))
print('The middle 5 sorted high to low:')
# removed on the basis that they are already sorted
#nums.sort()
nums.reverse()
print (*nums[1:6])
main()
It's just a lot nicer using range as you don't need to the i variable outside the scope of the loop.
This is one way to do it:
nums = []
for i in range(20,80,7):
nums.append(i)
mx = max(nums)
mn = min(nums)
nums.remove(mx)
nums.remove(mn)
mx2 = max(nums)
mn2 = min(nums)
nums.remove(mx2)
nums.remove(mn2)
nums.sort()
nums.reverse()
print nums
The output is the 5 middle numbers in descending order:
[62, 55, 48, 41, 34]
and the better, shorter way to do it is this:
def main():
nums = []
for i in range(20,80,7):
nums.append(i)
mx = max(nums)
mn = min(nums)
print "The highest number is %s " % mx
print "The lowest number is %s " % mn
while len(nums) != 5:
nums.remove(max(nums))
nums.remove(min(nums))
nums.sort()
nums.reverse()
print "The middle 5 sorted high to low is %s:" % nums
main()
The output is:
The highest number is 76
The lowest number is 20
The middle 5 sorted high to low is [62, 55, 48, 41, 34]

Categories

Resources