How to pass a list of dictionaries in a function? - python

I am working on a teacher grading system in Django. I want functionality in which there is some entry like subject id and student's marks from the frontend. My app on the backend takes these two-parameter and creates a list of dictionaries with subject id and marks and pass it on another function and that function will sum up all the marks and give me a total and next average and percentage etc. But right now, I am stuck with total only so, when I pass this list of dictionaries in a function it gives me an error.
def marks_calculation(marks_entry):
total = sum(item['marks'] for item in marks_entry)
return total
class Student_marks:
def entry(subject_id, marks):
while True:
value = input("Need to enter marks, Press 'y' for Yes, 'n' for No: ").lower()
if value == 'n':
break
try:
subject_id = int(input(f'Enter subject id: '))
marks=int(input(f'Enter marks: '))
except ValueError:
print(f'You can only try integers:')
continue
marks_entry=[]
marks_entry.append({
"subject_id": subject_id,
"marks": marks
})
total_marks = marks_calculation(marks_entry)
return total_marks
marks=0
subject_id= 0
b= Students_marks
b.entry(marks, subject_id)
error is:
It is not giving me a total marks
"c:/Users/Lenovo/Documents/TGS/controller.py"
Enter subject id: 1
Enter marks: 58
PS C:\Users\Lenovo\Documents\TGS>

Based on your new edited question, there are multiple issues with your current code -
The indentation is incorrect at places.
The try/except block should be under the while loop
Since you want to first put all the entries in the marks_entry, you should intialize it first and then append data to it. Currently, its being reset back to [] after every new entry that you get. So it will always have at most 1 element in it, when you are trying to sum it up.
The total should be calculated in the end once you exit out of the while loop
Here's a sample code built on top of yours -
def marks_calculation(marks_entry):
total = sum(item['marks'] for item in marks_entry)
return total
class Student_marks:
def entry(subject_id, marks):
marks_entry=[]
while True:
value = input("Need to enter marks, Press 'y' for Yes, 'n' for No: ").lower()
if value == 'n':
break
try:
subject_id = int(input(f'Enter subject id: '))
marks=int(input(f'Enter marks: '))
except ValueError:
print(f'You can only try integers:')
continue
marks_entry.append({
"subject_id": subject_id,
"marks": marks
})
total_marks = marks_calculation(marks_entry)
return total_marks
marks=0
subject_id= 0
b = Student_marks
total = b.entry(marks, subject_id)
print(f'Your total marks are {total}')
Sample Output:
Need to enter marks, Press 'y' for Yes, 'n' for No: y
Enter subject id: 1
Enter marks: 44
Need to enter marks, Press 'y' for Yes, 'n' for No: y
Enter subject id: 2
Enter marks: 23
Need to enter marks, Press 'y' for Yes, 'n' for No: y
Enter subject id: 3
Enter marks: 12
Need to enter marks, Press 'y' for Yes, 'n' for No: n
Your total marks are 79

There are a few problems with your class. First of all, since you used b.mark_calculation() I assume you tended to define this function within the class, which is not right now! So, calling it on the class would be wrong. you should call it like:
class Marks_entry:
def marks_entry(subject_id, marks):
#...
def marks_calculation(marks_entry):
total = sum(item['marks'] for item in marks_entry)
return total
Second, you called marks_calculation without referring to the class. If you are trying to call a function of class, in most of the cases, you should use self in order to call a function of an object right within itself. Meaning your code should be something like:
class Marks_entry:
def marks_entry(subject_id, marks):
# rest of code
marks_calculation = self.marks_calculation(marks_entry)
return marks_calculation
def marks_calculation(self,marks_entry):
total = sum(item['marks'] for item in marks_entry)
return total
Third, you call the class without () which seems to be wrong. You should use something like:
# Rest of code
b= Marks_entry()
Fourth, I can't understand your intention of using b.marks_calculation(marks, subject_id) since you have defined this function to get just one argument(just marks and notsubject_id ). If you want to pass more variables to your function, you should define them in the function before calling the function.

Related

Python Dict 2 argument, how to exit the while loop with one <enter>

Have written below program, but how to avoid the system checking the two argument when enter is pressed, we are using the enter key to exit the while loop.
while True: # need to exit the while loop thru one <Enter>
itemcode, quantity = input("Enter item code and quantity (Press <Enter> key to end): ") .split()
if itemcode == " " : #got two argument, one enter will crash the system, how to amend it
return
if itemcode not in orderdict.keys():
print("Invalid item code! Try again.")
continue
if itemcode in orderdict.keys():
orderdict [itemcode] = orderdict
#print("{:4s} {:<3d} {:<3d} X {:<3d} ".format(itemcode, [0], [1], [3]))
else :
input ()
break
Your problem is that the first line is hardcoded in such a way that the program expects two, and exactly two, values separated by a space. If you give it less than two (and simply hitting "enter" means giving it zero values), or more than two, this causes a traceback because the expected number of values isn't there.
If you don'T trust your users to enter the correct number of values, then I think you can avoid a crash either with a try/exception block, or a simple loop that repeats promtping the user for input until the number of entered values is exactly two:
while True:
entry_list = input("Enter item code and quantity (Press <Enter> key to end): ") .split()
if len(entry_list) == 2:
itemcode = entry_list[0]
quantity = entry_list[1]
break
You can start to ask the user to enter only the value of the item and check this value if it is an enter key, then break the loop. Otherwise, check the value of the item if it is within the keys if so, then ask the user for the corresponding quantity. I think you need to replace orderdict
with the corresponding quantity for the item entered by the user.
orderdict = {"car":50,"plane":60,"bus":100} # example
while True:
itemcode = input("Enter item code and quantity (Press <Enter> key to end): ")
if itemcode == "" :
break
elif itemcode not in orderdict:
print("Invalid item code! Try again.")
else:
orderdict [itemcode] = input("Enter the quantity: ")
Note: you do not need to write orderdict.keys(), you can use only the name of a dictionary to iterate through the keys of orderdict.

keep increasing the value of a variable in a function the more i call it

The first function simply takes a value (let's say 3)
The second function asks the user if they want to repeat the operation
If the user agrees to perform the operation again, and this time they enter 2
How can I make the final value of the variable be the addition of the two user inputs?
def value():
amt = int(input("enter value: "))
def go_again():
again = input("DO you want to go again(y/n)")
if again == "y":
value()
else:
exit()
value()
again()
(This is a shorter code but similar to what I am working on.)
Just embed value function in go_again and run it in while loop:
def value():
return int(input("enter value: "))
def go_again():
val = value()
while input("DO you want to go again(y/n)") == "y":
val += value()
exit()
go_again()

Loop - Input numbers to list, don't allow alphabetic input, break out by pressing enter ..?

been at this all day and made absolutely no progress, it's surely supposed to be pretty simple too but I'm new to Python. Google hasn't brought up much so this is my last resort!
It's supposed to be some basic code for manually putting numeric values into a list. If I add a 'print' line to the script I can see the values are being successfully entered as I go along, but I can't seem to add the right script for breaking out of the loop by leaving the input blank. Currently if I set anything to make it break, the script seems to freeze while it's running and I have to reset the console completely.
Also I'm wondering is there a way of ensuring the input is always an integer? It would be good to make things a bit cleaner and bring up an error message or something if the user enters anything non-numeric.
Here's the code.
values = []
while True:
a = raw_input('Enter numeric values. Leave blank to stop: ')
if a == (??????) :
break
values.append(float(a))
Thanks!
You can restrict to only numbers with
if a.isdigit():
So your function could look like
def accept_inputs():
values = []
while True:
a = raw_input('Enter numeric values. Leave blank to stop: ')
if a.isdigit():
values.append(float(a))
if not a:
return values
Testing
>>> accept_inputs()
Enter numeric values. Leave blank to stop: 5
Enter numeric values. Leave blank to stop: 42
Enter numeric values. Leave blank to stop: 73
Enter numeric values. Leave blank to stop: ab
Enter numeric values. Leave blank to stop: abc
Enter numeric values. Leave blank to stop:
[5, 42, 73]
My approach is similar to #CoryKramer, with small changes
>>> values = []
>>> while True:
val = raw_input('Enter Number : ')
if not val:
print values
elif val.isdigit():
values.append(int(val))
else:
print 'you have entered non - digit value'
Enter Number : 2
Enter Number : a
you have entered non - digit value
Enter Number : 3
Enter Number : 5
Enter Number : 6
Enter Number : 22
Enter Number : 546
Enter Number : 31s
you have entered non - digit value
Enter Number : 345678
Enter Number :
>>> values
[2, 3, 5, 6, 22, 546, 345678]
Strings have a built in function isdigit() that returns true if all the characters are numbers.
To break out if nothing is entered, use the len() function to detect if the string is empty.
More info here
You're code would look like this:
if a.isdigit():
#keep going, and add it to the list
elif len(a) == 0:
break #stop the loop

Why does this loop have only one iteration instead of the number of iterations entered by the user? [duplicate]

This question already has answers here:
Python: raw_input and unsupported operand type(s)
(3 answers)
Closed 7 years ago.
I am trying to ask the user to enter any number and then ask the user to enter any names, then store this input in a list.
However, when I enter any number, it asks to enter name only one time and shows the output in list:
def main():
# a = 4
a = input("Enter number of players: ")
tmplist = []
i = 1
for i in a:
pl = input("Enter name: " )
tmplist.append(pl)
print(tmplist)
if __name__== "__main__":
main()
output:
Enter number of players: 5
Enter name: Tess
['Tess']
The for loop should run 5 times and user entered 5 values get stored in a list.
You need to convert the number of players to integer and then loop for that much amount of times, you can use the range() function for this . Example -
def main():
num=int(input("Enter number of players: "))
tmplist=[]
for _ in range(num):
pl=input("Enter name: " )
tmplist.append(pl)
print(tmplist)
Since you are using Python3
a=input("Enter number of players: ")
means a is a string "5". Since this is only one character long - the loop will run just once
You need to use
a = int(input("Enter number of players: "))
You'll also need to change the loop
for i in range(a):
I recommend using more meaningful variable names - especially if this is homework
def main():
number_of_players = int(input("Enter number of players: "))
player_list = []
for i in range(number_of_players):
player = input("Enter name: " )
player_list.append(player)
print(player_listlist)
if __name__== "__main__":
main()
You got a string a which presumably contained something like '5'. Then you initialize a counter i. Then you loop through this string, which, since it's '5', resulted in one iteration, because there's only one character in '5'.
First you have to change it into a number, with a = int(a).
With a as a number, you still can't loop through that, because a number isn't an iterable.
So then you should create a range object to loop over, with for i in range(a):.
Then you will be able to carry out your operations as expected.
Since the input a is a string
you need to convert it to a number and then use a different for.
it should be
def main():
#a=4
a=int(input("Enter number of players: "))
tmplist=[]
i=0
while i < a:
pl=input("Enter name: ")
tmplist.append(pl)
i+=1
print(tmplist)
main()

Beginner Index out of range in python

This is a problem I am working on for a class (below is my question and the code I wrote):
The program should accept a series of students and their exam scores in response to a
"?" prompt. Enter the two digit exam score (no one ever gets 100 or less than 10), a single
space and the name of the student. Keep entering these until the user enters "Stop" –
your program should be able to handle any form of "Stop" – for example, "stop", "Stop",
"STOP", "sTOP", etc.
You should then display a list of student names ordered by their exam scores (low to
high).
For instance (user input is underlined):
? 23 Warren
? 44 Dona
? 33 Tom
? stop
Warren
Tom
Dona
So I understand everything I've written and I understand that this is not an especially complicated problem. Though, the way my code is written, when I input "stop" to show the program that I am finished with inputs, it runs the input "stop" in the for loop creating a index out of range error. How can I make it run "stop" only in the while loop and not in the for loop?
students = []
nameScore = ""
while (nameScore.lower() != "stop"):
nameScore = input ("? ")
students.append(nameScore)
students.sort()
for student in students:
x = student.split()
print (x[1])
If you "break" before you append, then "stop" will not be included in students.
while True:
nameScore = input ("? ")
if nameScore.lower() == "stop": break
students.append(nameScore)
Moreover, if you write the while-loop this way, you won't need to pre-initialize nameScore.
You can change the flow of the program just a bit and have it "prime" the input string before entering the while loop; that way it'll check before it appends the input:
students = []
nameScore = input("? ")
while nameScore.lower() != "stop":
students.append(nameScore)
nameScore = input ("? ")
students.sort()
for student in students:
x = student.split()
print (x[1])
A bit of code repetition, but it does the job.
Another way to do it is to use a list slice to remove the last element:
students = []
nameScore = ""
while nameScore.lower() != "stop":
students.append(nameScore)
nameScore = input ("? ")
students = students[:-1] # Remove the last element
students.sort()
for student in students:
x = student.split()
print (x[1])
By the way, the parenthesis around the while condition aren't necessary in Python.

Categories

Resources