Python Using a For loop inside a function - python

I'm a Python beginner trying write a program that will allow the user to input individuals names and test scores and I am supposed to give back a grade after finding the average so far I've been able to write the program but I am experiencing difficulties trying to debug it.
my programs works fine until it starts to calculate the average, it usually displays an error message saying
"TypeError: 'float' object is not subscriptable"
Could somebody please help me why my codes are not working? Thank you for your help in advance!
def calcaverage(test1,test2,test3):
for count in range(numofstudent):
curraverage=((test1[count]+ test2[count]+ test3[count])/3)
if curraverage>= 90:
grade= "A"
return grade
else:
if curraverage >= 80 and curraverage < 90:
grade= "B"
return grade
else:
if curraverage >= 70 and curraverage < 80:
grade= "C"
return grade
else:
if curraverage < 70:
grade= "F"
return grade
numofstudent=int(input("How Many Students?: "))
students=[]
test1=[]
test2=[]
test3=[]
averagescore=[]
grade=[]
for count in range(numofstudent):
currstudent=input("Please enter name of student: ")
students.append(currstudent)
currstudenttest1= float(input("First test score?: "))
currstudenttest2= float(input("Second test score?: "))
currstudenttest3= float(input("Third test score?: "))
test1.append(currstudenttest1)
test2.append(currstudenttest2)
test3.append(currstudenttest3)
grade=calcaverage(test1,test2,test3)
averagescore.append(grade)
print([students], "your grade is " ,[grade])

Here comes some tough love.
There are multiple problems here. In general you need to learn to think through your program line by line, as though you were the CPU, and figure out what you want to happen at each step. Then you need to weed out mistakes until what the actual CPU does is equal to what you want.
In the second line (the for loop), the variable "curraverage" is undefined since it doesn't get defined until a couple lines later. It's the wrong variable anyway; you want to loop over all the students so you need range(numofstudent).
In the next line, "test" is undefined. You meant "test3." If you want to learn to program you just cannot allow yourself to make these kinds of mistakes.
The variable curraverge looks like a typo, but it's actually not. Think of a better name, it's not hard.
In line 5, averagescore (which was declared as a global down below, and was a list) is now re-declared as a local and bound to a float. As such you cannot append to it in line 6. Line 5 should simply be discarded, it does nothing except create a bug.
The line grade[count] doesn't do anything. You need to call grade.append to build the list of grades. But since you haven't computed the grade yet, no such line belongs here.
Next you compare averagescore to 90 and 80 and so forth, but that's the wrong variable again. That's the list you declared below. Here you want the score for one student (which is curraverage).
Then you return from inside the loop, causing the function to exit before you have computed more than one grade. None of those returns should be in there.
I could go on. You need to be much, much more careful about what you are doing. Keep in mind that computers are profoundly stupid - they do exactly what they're told, whether that's what you want them to do or not.
Best of luck to you.

Here is a working example which uses some more advanced ideas:
we split the code into functions; each function does one specific thing. This makes the code much easier to think about, test, debug, and reuse.
each function has a docstring - built-in documentation about what it does and how to use it, which can be reviewed with Python's help() function, ie help(average).
we define a Student class which stores the name and marks for a single student. It knows how to create a student by prompting for input, and how to calculate an overall grade from the marks.
marks are entered using a list comprehension; something like
result = [func(x) for x in lst]
which is an easier-to-read equivalent of
result = []
for x in lst:
result.append(func(x))
Here's the code; if you trace through it and understand it, it should help:
# assumes Python 3
def get_int(prompt):
"""
Prompt the user to enter a number;
return the number as an int
"""
while True:
try:
return int(input(prompt))
except ValueError: # couldn't parse as int
pass # skip the error message
def average(lst):
"""
Return the average of a list of numbers
"""
return sum(lst) / len(lst)
def grade(mark):
"""
Given a mark as a percentage,
return a grade letter
"""
if mark >= 90.:
return "A"
elif mark >= 80.:
return "B"
elif mark >= 70.:
return "C"
else:
return "F"
class Student:
#classmethod
def from_prompt(cls):
"""
Prompt for a student's information,
return it as a Student object
"""
name = input("Please enter student name: ")
marks = [float(f) for f in input("Please enter {}'s marks: ".format(name)).split()]
return cls(name, marks) # implicitly calls __init__
def __init__(self, name, marks):
self.name = name
self.marks = marks
def grade(self):
"""
Return the student's overall grade
"""
return grade(average(self.marks))
def main():
# get student data
num_students = get_int("How many students do you want to enter? ")
print("")
students = [Student.from_prompt() for _ in range(num_students)]
# print student grades
print("")
for student in students:
print("{}'s grade is {}".format(student.name, student.grade()))
if __name__=="__main__":
# if loaded as a program, call the main function
main()
and runs like
How many students do you want to enter? 4
Please enter student name: Anna
Please enter Anna's marks: 91.0 94.5 96.1
Please enter student name: Ben
Please enter Ben's marks: 82 86 90
Please enter student name: Charlie
Please enter Charlie's marks: 65 75 85
Please enter student name: Farquad
Please enter Farquad's marks: 10 40 55 36 51 16
Anna's grade is A
Ben's grade is B
Charlie's grade is C
Farquad's grade is F

Related

why is the return of the program not good?

I'm new to python and there's a video on Youtube that I watched. I do the exact same code as he but mine doesn't work and I don' understand why.
Here's the code:
MAX_LINES = 3
def deposit():
while True:
amount = input("What would you like to deposit? $")
if amount.isdigit():
amount = int(amount)
if amount > 0:
break
else:
print("Amount must be greater than 0. ")
else:
print("Please enter a number. ")
return amount
def get_number_of_lines():
while True:
lines = input("Enter the number of lines to bet on (1-" + str(MAX_LINES) + ")? ")
if lines.isdigit():
lines = int(lines)
if 1 <= lines <= MAX_LINES:
break
else:
print("Please enter a valid number of lines. ")
else:
print("Please enter a number. ")
return lines
There are 3 problems.
Unindent amount does not match previous indent. I have no idea what does that mean
"return" can be used only within a function. As far as I'm concerned I'm using it in the function, copied the first function then pasted it into the second function and somehow it doesn't work
"lines" is not defined. What dou you mean it's not defined, I define it in the first line of the function
https://www.youtube.com/watch?v=th4OBktqK1I
This video's code what I'm trying to do
I appreciate any help!
I just simply don't understand why it works in one and not the other
You have one space too much in front of while True in function get_number_of_lines().
Yes used in functions to return value
Because function don't get inside while loop (because of indent problem), lines is never defined, probably this was the problem.
So try fix indent and run again

How do I successfully close the While loop in this code? It seems to not recognize my break condition?

The prompt for the problem goes as follows:
Create an interactive student records system.
Prompt the user for a student name.
Then prompt the user for a numeric grade
Repeat this until the user enters 'done' in place of a name.
Then print each student and the average of their grades
I have come up with the following code (I'm a beginner guys, sorry if this is obvious)
# I am creating a dictionary so I can store multiple values that are associated with one name
lst = []
dict = {}
while True:
try:
name = str(input("Please enter student's name."))
grade = int(input("Please enter grade student recieved."))
if (name not in list(dict.keys()) and name != "done"):
lsst = []
lsst.append(grade)
dict[name] = lsst
print(lsst)
continue
elif name in list(dict.keys()):
lsst.append(grade)
print(lsst)
continue
elif name == "done":
break
except ValueError:
print("Try Again")
pass
for i in range(list(dict.keys())):
print(f"{name}: {grade}")
I am trying to print the averages after I type 'done' for the name input, but it just moves on to the next input inquiry. Why is this, and how do I fix it?
There are many mistakes in the code but I will break them down in my corrected version.
names_and_grades = {} # I renamed this variable because there is a built in type called dict in Python.
while True: # Using while True is usually discouraged but in this case, it's hard to avoid that.
try:
name = input("Please enter student's name.") # No need to convert to string as it takes the input as a string by default.
if name == "done": # After you prompted for a name immediately check whether the user entered done. This way, you can break right after that.
break
grade = int(input("Please enter grade student recieved."))
if name not in names_and_grades.keys():
names_and_grades[name] = [grade] # We don't actually need a separate list as the entry in the dictionary will be the list itself (that's why it's put between brackets).
elif name in names_and_grades.keys():
names_and_grades[name].append(grade) # Once the list was declared, you can simply append it.
print(names_and_grades[name]) # No need to repeat this twice in the if-else statements, you can just write it after them. And a very important thing, there is no need to use continue, since you are using if-elfe. When you are using if-else, only one of the blocks will be used, the first block where the condition evaluates as true.
except ValueError:
print("Try Again")
for k in names_and_grades.keys():
print(f"{k}: {names_and_grades[k]}") # This is the simplest way to iterate through a dictionary (if you want to format the entries), by iterating through the keys of the dictionary and with the help of the keys, calling the appropriate values.
I hope this helps, let me know if something is unclear.
#I8ACooky - there are some logic and syntax errors, so I will suggest you to run this and see if you can get some ideas to work out your own later:
from collections import defaultdict
grades = defaultdict(list) # in case for multiple scores for a student
print('Welcome to the simple Scoring program. ')
while True:
try:
name = input("Please enter student's name.")
score = int(input("Please enter grade student recieved: "))
if name == 'done' and score == 0:
break
grades[name].append(score)
except ValueError:
print('Try Again....?')
print(dict(grades))
#------------------------
# average scores leave as an exercise...
Outputs:
Welcome to the simple Scoring program.
Please enter student's name.Adam
Please enter grade student recieved: 100
Please enter student's name.Bob
Please enter grade student recieved: 60
Please enter student's name.Cindy
Please enter grade student recieved: 80
Please enter student's name.Adam
Please enter grade student recieved: 80
Please enter student's name.Bob
Please enter grade student recieved: 100
Please enter student's name.Cindy
Please enter grade student recieved: 90
Please enter student's name.done
Please enter grade student recieved: 0
{'Adam': [100, 80], 'Bob': [60, 100], 'Cindy': [80, 90]}

How do you let user pick the range for for loop?

I have to make this program:
Write a program that allows a teacher to input how many students are in his/ her class, then allow them to enter in a name and mark for each student in the class using a for loop. Please note you do not need to record all of the names for later use, this is beyond the scope of the course * so just ask them each name, have it save the names over top of each other in ONE name variable.
i.e.)
INSIDE OF A LOOP
name = input (“Please enter student name: “)
Calculate the average mark for the entire class – this will require you to use totaling.
Output the class average at the end of the program, and ask if they would like to enter marks for another class. If they say yes, re-loop the program, if no, stop the program there.
So I started writing the program and it looks like this
studentamount = int(input("Please enter how many students are in your class: "))
for count in range():
name = input ("Please enter student name: ")
mark = int(input("Please enter the student's mark"))
I ran into the following problem: how would I allow the set of code under the for loop to loop for each student? I was thinking I could just enter in the studentamount variable as the range but I can't since python does not allow you to enter in a variable as a range.
How would I get the for loop to loop for the amount of students typed in? e.g. if 20 students for student amount was typed in, I would want the for loop to loop 20 times. Your help and knowledge is much appreciated.
Read the user input, convert it to int and pass it as a parameter to range:
studentamount = input("Please enter how many students ...: ") # this is a str
studentamount = int(studentamount) # cast to int ...
for count in range(studentamount): # ... because that's what range expects
# ...
Python does not allow you to enter in a variable as a range.
Python does allow you to enter variables as a range, but they must be numbers. Input () reads input in as string, so you need to cast it.
So, this is correct:
```Python
studentamount = int(input("Please enter how many students are in your class: "))
for count in range(studentamount):
name = input ("Please enter student name: ")
mark = int(input("Please enter the student's mark)
```
P.S a try - except clause would be useful here to catch people entering a non-integer data in [TypeError]
P.S.P.S #schwobaseggl 's example is good too, it is possibly more pythonistic to use the nested function studentamount = int(input("Text") than
studentamount = input("Text")
studentamount = int(studentamount)
You can store each student name and mark in a dictionary or tuple and store each dictionary (or tuple) into a list, see code sample (at the end enter "no" to exit or any other value to re-loop the program):
response = None
while response != 'no':
student_count = int(input('Please enter the number of students: '))
students = []
mark_sum = 0
print('There are {} student(s).'.format(student_count))
for student_index in range(student_count):
student_order = student_index + 1
student_name = input('Please enter the name of student number {}: '.format(student_order))
student_mark = float(input('Please enter the mark of student number {}: '.format(student_order)))
students.append({'name': student_name, 'mark': student_mark})
mark_sum += student_mark
print('The average mark for {} student(s) is: {}'.format(student_count, mark_sum / student_count))
response = input('Do you want to enter marks for another class [yes][no]: ')

Making a statistics program

I am trying to write a Python program that computes and prints the following :
the average score from a list of scores
the highest score from a list of scores
the name of the student who got the highest score.
The program starts by asking the user to enter the number of cases. For EACH case, the program should ask the user to enter the number of students. For each student the program asks the user to enter the student's name and marks. For EACH case the program reports the average marks, the highest marks and the name of the student who got the highest marks.
Also
If there are more than one person with the highest score in a CASE, the program should report the first occurrence only.
The average score and the highest score should have exactly 2 decimal places.
The output should be as in the sample program output.
What I have been trying so far is the following:
grade=[]
name_list=[]
cases=int(input('Enter number of cases: '))
for case in range(1,cases+1):
print('case',case)
number=int(input('Enter number of students: '))
for number in range (1,number+1):
name=str(input('Enter name of student: '))
name_list.append(name)
mark=float(input('Enter mark of student:'))
grade.append(mark)
highest= max (grade)
average=(sum(grade)/number)
high_name=grade.index(max(grade))
print('average',average)
print('Highest',highest)
print (high_name)
This is what i have deciphered so far. my biggest problem now is getting the name of the individual with the high score. Any thoughts and feedback is much appreciated. As with respect to the answer posted below, i am afraid the only thing i do not understand is the dictionary function but otherwise the rest does make sense to me.
This resembles an assignment, it is too specific on details.
Anyways, the official docs are a great place to get started learning Python.
They are quite legible and there's a whole bunch of helpful information, e.g.
range(start, end): If the start argument is omitted, it defaults to0
The section about lists should give you a head start.
numcases = int(input("How many cases are there? "))
cases = list()
for _ in range(numcases):
# the _ is used to signify we don't care about the number we're on
# and range(3) == [0,1,2] so we'll get the same number of items we put in
case = dict() # instantiate a dict
for _ in range(int(input("How many students in this case? "))):
# same as we did before, but skipping one step
name = input("Student name: ")
score = input("Student score: ")
case[name] = score # tie the score to the name
# at this point in execution, all data for this case should be
# saved as keys in the dictionary `case`, so...
cases.append(case) # we tack that into our list of cases!
# once we get here, we've done that for EVERY case, so now `cases` is
# a list of every case we have.
for case in cases:
max_score = 0
max_score_student = None # we WILL need this later
total_score = 0 # we don't actually need this, but it's easier to explain
num_entries = 0 # we don't actually need this, but it's easier to explain
for student in case:
score = case[student]
if score > max_score:
max_score = score
max_score_student = student
total_score += score
num_entries += 1
# again, we don't need these, but it helps to demonstrate!!
# when we leave this for loop, we'll know the max score and its student
# we'll also have the total saved in `total_score` and the length in `num_entries`
# so now we need to do.....
average = total_score/max_entries
# then to print we use string formatting
print("The highest score was {max_score} recorded by {max_score_student}".format(
max_score=max_score, max_score_student=max_score_student))
print("The average score is: {average}".format(average=average))

Trying to calculate highest marks with name in python

grade=[]
names=[]
highest=0
cases=int(input('Enter number of cases: '))
for case in range(1,cases+1):
print('case',case)
number=int(input('Enter number of students: '))
for numbers in range (1,number+1):
name=str(input('Enter name of student: '))
names.append(name)
mark=float(input('Enter mark of student:'))
grade.append(mark)
print('Case',case,'result')
print('name',list[list.index(max(grade))])
average=(sum(grade)/number)
print('average',average)
print('highest',max(grade))
print('name',names[grade.index(max(grade))])
I want to print name of the student with the highest mark. I have not learned anything other than list, while and for. NO dictionary ..nothing. I was wondering how can i do this?
ALSO i am getting this error!!! builtins.AttributeError: 'str' object has no attribute 'append'. HELP. thank you! :D
for number in range (1,number+1):
Don't reuse variable names for different things, call one of them numbers and the other number:
numbers=int(input('Enter number of students: '))
for number in range (1,numbers+1):
You made name a list in the beginning:
name=[]
but here you assign a single input to it:
name=str(input('Enter name of student: '))
The you append the new name to itself:
name.append(name)
which is not possible, because name is after the input no longer a list but a string. Again using different variable names for different things would help. Call the array names and the single input name:
names = []
#...
name=str(input('Enter name of student: '))
names.append(name)
And here:
print('name',list[list.index(max(grade))])
list is a build-in type, not one of your variables, so what you are trying to do is index a type, not a specific list. If you want to call index on a specific list you do so by using the variable name of that list. grade.index(...) will find the specific position matching the passed grade in grade and then you can use this position to get the corresponding name, because you know, that the name is at the same position in names:
print('name',names[grade.index(max(grade))])
Here is a somewhat more elaborated version; working through it should give you a better feel for the language.
from collections import namedtuple
import sys
# Python 2/3 compatibility shim
if sys.hexversion < 0x3000000:
inp, rng = raw_input, xrange # Python 2.x
else:
inp, rng = input, range # Python 3.x
def type_getter(type):
"""
Build a function to prompt for input of required type
"""
def fn(prompt):
while True:
try:
return type(inp(prompt))
except ValueError:
pass # couldn't parse as the desired type - try again
fn.__doc__ = "\n Prompt for input and return as {}.\n".format(type.__name__)
return fn
get_int = type_getter(int)
get_float = type_getter(float)
# Student record datatype
Student = namedtuple('Student', ['name', 'mark'])
def get_students():
"""
Prompt for student names and marks;
return as list of Student
"""
students = []
while True:
name = inp("Enter name (or nothing to quit): ").strip()
if name:
mark = get_float("Enter {}'s mark: ".format(name))
students.append(Student(name, mark))
else:
return students
def main():
cases = get_int("How many cases are there? ")
for case in rng(1, cases+1):
print("\nCase {}:".format(case))
# get student data
students = get_students()
# perform calculations
avg = sum((student.mark for student in students), 0.) / len(students)
best_student = max(students, key=lambda x: x.mark)
# report the results
print(
"\nCase {} average was {:0.1f}%"
"\nBest student was {} with {:0.1f}%"
.format(case, avg, best_student.name, best_student.mark)
)
if __name__=="__main__":
main()
which runs like:
How many cases are there? 1
Case 1:
Enter name (or nothing to quit): A
Enter A's mark: 10.
Enter name (or nothing to quit): B
Enter B's mark: 20.
Enter name (or nothing to quit):
Case 1 average was 15.0%
Best student was B with 20.0%

Categories

Resources