How to call nested functions? - python

Pointers on how to fix my code? This code asks for user input on the number of tickets sold, and returns the income generated using functions
I am not sure about what how to call each function
secA = 20
secB = 15
secC = 10
def main():
print("The income generated from all sections is: ", total)
def getTickets(A,B,C):
sectionA = int(input("Please enter the number of tickets sold in section A: ")
sectionB = int(input("Please enter the number of tickets sold in section B: ")
sectionC = int(input("Please enter the number of tickets sold in section C: ")
def ticketsValid():
while sectionA > 300:
print("ERROR: Section A has a limit of 300 seats")
while sectionB > 500:
print("ERROR: Section B has a limit of 500 seats")
while sectionC > 200:
print("ERROR: Section C has a limit of 200 seats")
def calcIncome():
total = secA * sectionA + secB * sectionB + secC * sectionC
print("The income generated is $", format(total, '.2f'))
main()

To answer your first question: to call all of the functions you need to put the names of your functions into the main() function. But, you had several other errors so I have decided to walk you through the program, step-by-step.
First, we set the prices:
secA = 20
secB = 15
secC = 10
Here is the first function, getTickets()
def getTickets():
global A
A = int(input("Please enter the number of tickets sold in section A: "))
global B
B =int(input("Please enter the number of tickets sold in section B: "))
global C
C =int(input("Please enter the number of tickets sold in section C: "))
Notice the word global before I use the variable. This tells the computer that this variable can be used everywhere. Next, notice the double parentheses - since both int() and input() are functions, so we need to show that by doing that.
I fixed your code for the ticketsValid() function. Usually, it isn't a good idea to nest functions, so this is at the same indentation level as the above code.
def ticketsValid(A,B,C):
while A > 300 or A < 0:
print("ERROR: Section A has a limit of 300 seats\n")
A = int(input("Please enter the number of tickets sold in section A: "))
while B > 500 or B < 0:
print("ERROR: Section B has a limit of 500 seats")
B =int(input("Please enter the number of tickets sold in section B: "))
while C > 200 or C < 0:
print("ERROR: Section C has a limit of 200 seats")
C =int(input("Please enter the number of tickets sold in section C: "))
This gets the variables from above, and checks to see if they are valid. Notice that I added a check for negative numbers - you can't sell negative tickets.
Then we come to calcIncome(A,B,C):
def calcIncome(A, B, C):
total = A * secA + B * secB + C * secC
print ("The income generated is $%d" % (total))
First, we multiply the sections by the set prices to calculate the total. Then, we print it.
Lastly, we need to call the functions. I used your idea for a main() function, which uses the other functions. It looks like this.
def main():
getTickets()
ticketsValid(A,B,C)
calcIncome(A, B, C)
It simply calls the other functions, in the correct order, when run.
Lastly, we call the main() function by typing:
main()
I hope that this answered your question. If not, feel free to comment. If so, please check the green check mark next to my answer.

If you only want to know how to use a nested function:
def f():
def g(): #this defines a function but does not call it
print "run g"
g() # this calls g.
Typically, nested functions should not be available outside its parent function. Since the point of using a nested function is that the function only helps its parent function to do things. If you want it outside, consider define it as a new function.
In your case, you need to consider how to break up your code into parts.
If I were you, I would use getTickets() to get tickets.
The ticketsValid is fine, though I would let it return a boolean.
calcIncome would return the total income.
So the general design is like:
def main():
(A, B, C) = getTickets()
if(ticketsValid(A, B, C)):
income = calcIncome(A, B, C)
print("The income generated from all sections is: ", income)
def getTickets():......
def ticketsValid(A, B, C):......
def calcIncome(A, B, C):......
I think this would be a better design.

Related

Is there any way to make this any more efficient?

I'm a beginner to programming, I literally started programming like three days ago. Here is my program, it checks if you've passed all subjects, and as you guys can see, there are a lot of if conditions in it. I've read online that too many if conditions, or for loops can slow your program down, and that there is a more efficient way of doing it, that is by using some user-defined function. But, the problem is that I don't have the necessary knowledge to do so. It would be really helpful if you guys can tell me how to shrink my code down, and maybe make it more efficient.
# Take input
while True:
a = float(input("Enter your mark in Tamil: "));
b = float(input("Enter your mark in English: "));
c = float(input("Enter your mark in Chemistry: "));
d = float(input("Enter your mark in Physics: "));
e = float(input("Enter your mark in Non-major: "));
f = float(input("Enter your mark in Python: "));
# This part checks if you've got a minimum of 35% in every subject
if a >= 35.0 and a <= 100.0:
print("Pass in Tamil")
if a > 100.0:
print("Invalid input")
if a < 35.0:
print("Fail in Tamil")
if b >= 35.0 and b <= 100.0:
print("Pass in English")
if b > 100.0:
print("Invalid input")
if b < 35.0:
print("Fail in English")
if c >= 35.0 and c <= 100.0:
print("Pass in Chemistry")
if c > 100.0:
print("Invalid input")
if c < 35.0:
print("Fail in Chemistry")
if d >= 35.0 and d <= 100.0:
print("Pass in Physics")
if d > 100.0:
print("Invalid input")
if d < 35.0:
print("Fail in Physics")
if e >= 35.0 and e <= 100.0:
print("Pass in Non-major")
if e > 100.0:
print("Invalid input")
if e < 35.0:
print("Fail in Non-major")
if f >= 35.0 and f <= 100.0:
print("Pass in Python")
if f > 100.0:
print("Invalid input")
if f < 35.0:
print("Fail in Python")
# Display the total marks and the percentage secured by the user
if (a>100 or b>100 or c>100 or d>100 or e>100 or f>100):
print("Check your marks")
if (a<=100 and b<=100 and c<=100 and d<=100 and e<=100 and f<=100):
print("Your total:", a+b+c+d+e+f)
print("Your percentage:", ((a+b+c+d+e+f)/600)*100)
# Check if the user wants to do another calculation
next_calculation = input("Do you want to proceed with next calculation? (yes/no) ")
if next_calculation == "no":
break
if next_calculation != ("yes" or "no"):
print("Invalid input")
break```
Well done! And welcome to StackOverflow.
Codereview versus StackOverflow
This site (Stackoverflow) is for developers who are stuck at a problem. There is a sister-site, CodeReview, which does only that: reviewing code. Your question is a bit between both sites: you have a question (can this be more efficient / Pythonic), but your question is mostly a code review question. Check out the "How to ask" sections of both sites for more info.
Use functions
As I said: you're doing a great job. You're doing input, output (print) and if-then statements. You even have comments in your code, explaining what you're doing. Wonderfull!
Next step is to decompose your code into logical functions. I see that your comments are already pointing in the right direction (for example: "Take input" does exactly that). Now create a function (def function_name(function_arguments):) and think about what that function needs as input (function arguments) and what it should output (return value). For example in your code, you could have the following functions:
Ask the user for marks for a class. Input: class name. Output: a valid mark.
Print if the user failed or passed. Input: class name, mark.
You can create functions that perform this task. This cuts your code input (re)usable and manageable pieces. Add a comment at the beginning of the function that describes what it does.
Learn about lists and dicts
Lists and Dicts (dictionaries) are extremely useful datatypes in Python. Learn them. I included them in the example below. More (general) info on lists, dicts, sets, etc. in the official Python documentation or anywhere on the web.
Code style: PEP8
Try to code according to general accepted styling rules, called PEP8. Most important examples (for you as a beginner):
Give your variables meaningful names (not: a, b, c, etc.).
Don't use "magic numbers" in your code (0, 35, 100, 'yes', etc.). Create constants, define them at the top of the module, give them names in capitals (MEANING_OF_LIFE = 42).
Use 4 spaces as identation (not 1).
"More efficient" version of your code
Here is a rewrite of your code. I really hope this helps. There are many other ways to do this. But I tried to keep it simple and meaningful for you as a beginner.
MIN_MARK = 0.0
PASS_MARK = 35.0
MAX_MARK = 100.0
YES = ['yes', 'y']
def get_marks(classname: str) -> float:
""" Asks a mark for the given classname.
Checks the mark for a numeric value and
that the mark is between MIN_MARK and MAX_MARK (both included)
"""
while True:
mark = input(f'Enter your mark in {classname}: ')
if mark.isnumeric():
mark = float(mark)
if mark >= MIN_MARK and mark <= MAX_MARK:
return mark
else:
print(f'Enter a mark between 0 and 100; please try again!')
else:
print(f'{mark} is not a valid numeric value; please try again!')
def print_pass_or_fail(classname: str, mark: float) -> None:
""" Prints if classname is passed or failed.
Class if passed if mark >= PASS_MARK.
"""
if mark > PASS_MARK:
result = 'PASS'
else:
result = 'FAIL'
print(f'{result} in {classname} with scoe {mark}')
def main():
classes = ['Tamil', 'English', 'Chemistry',
'Physics', 'Non-major', 'Python']
marks = {}
proceed = True
while proceed:
for classname in classes:
marks[classname] = get_marks(classname)
for classname, grade in marks.items():
print_pass_or_fail(classname, grade)
print(f'Totale score: {sum(marks.values())}')
print(f'Average score: {sum(marks.values()) / len(marks) * 100}%')
proceed = input('Continue [y/n]')
proceed = proceed.lower() in YES
if __name__ == '__main__':
main()
Try it online!
comparing your code to another people's code is huge growing point, stackoverflow helps a lot with it
while int(input("Do you want to proceed with next calculation? '1' - yes, 0 - 'no': ")):
d = {i:float(input(f"Enter your mark in {i}: ")) for i in ['Tamil', 'English', 'Chemistry', 'Physics', 'Non-major', 'Python']}
l = [f"Pass in {k}" if 35 <=v <= 100 else ("Invalid input" if v>100 else f"Fail in {k}") for k,v in d.items()]
# This part checks if you've got a minimum of 35% in every subject
for i in l:
print(i)
# Display the total marks and the percentage secured by the user
if 'Invalid input' in l:
print('Check your marks')
else:
print("Your total: ", sum(d.values()))
print("Your percentage: ", sum(d.values())/600*100)
print("\n",'*'*40,'\n\n\n')
print('see you later!')

How to make a variable hold a maximum amount of arguments

I'm very new to python and I don't know much. My goal is to make a calculator that asks how many arguments you want to multiply together. Unfortunately, I don't know how to do that. I made a very beta version of this
nums = []
class mathFunc():
def multiply():
f = input("How many arguments: ")
argz = float(f)
while argz>0:
argz = argz - 1
nums.append(argz)
##################
length = len(nums)
print(length)
mathFunc.multiply()
Does anyone have any tips? Please lmk!
The simple mechanism is just to ask for numbers until they hit "enter" to stop entering numbers:
def multiply():
product = 1
while 1:
f = input("What's the next number? ")
if f == '':
return product
product *= float(f)
print("Total so far is", product)
print(multiply())

Functions and Finding Averages

I started Python last week and this is the question my teacher wants us to solve: Write a function named average_of_3 that accepts three integers as parameters and returns the average of the three integers as a number. For example, the call of average_of_3(4, 7, 13) returns 8.
Functions are very confusing to me but this is what I have so far...
def average(num1, num2, num3):
avg = (num1) + (num2) + (num3)/3
return (avg)
num1 = int(input("Enter a number: "))
num2 = int(input("Enter a number: "))
num3 = int(input("Enter a number: "))
I'm not sure if this is right or not... I'm also not sure what to do after this.
Think of a function as a cook. You give the cook some ingredients and the cook gives you back a delicious dish. When you define the function, you "teach the chef how to cook" by telling Python what ingredients it takes, what it does to the ingredients, and what it gives back.
So you can ask your user what "ingredients they want to give your chef" like so:
a = int(input("Enter a number: "))
b = int(input("Enter a number: "))
c = int(input("Enter a number: "))
But you still need to give the chef those ingredients. You do that by calling the function like so:
answer = average(a, b, c)
Side note: The chef can have its own names for the ingredients, so even though you defined them as a, b, c while asking the user, when you pass them to the function, the function accesses them as num1, num2, num3 because that's how the function is defined.
Then you can do whatever you want with answer, such as print(answer)
Oh, and another thing: remember PEMDAS / BEDMAS / whatever you call the order of operations in mathematics? Such a concept exists in programming too. If you simply do
avg = 1 + 2 + 3 / 3
You get avg = 4. Instead, surround the entire sum in parentheses so that you actually get the average
avg = (1 + 2 + 3) / 3
this can be done using optional argument or using a list of your values
def averaged(*args):
return sum(args)/len(args)
#or
def averaged1(args: list):
return sum(args)/len(args)
#------------------------------
print(averaged(3,4,5))
print(averaged1([3,4,5]))
4.0
4.0
you could simply implement this like:
num = None
nums = []
while True:
num = int(input("value: "))
if num !=0: nums.append(num)
else: break
def averaged1(args: list):
return sum(args)/len(args)
print(averaged1(nums))
value: 1
value: 2
value: 3
value: 0 # <-- breaks here
2.0
def average_of_3(num1, num2, num3):
return (num1 + num2 + num3)/3
# call your func
average_of_3(4, 7, 13)
You need to pass your numbers as arguments of the function, if you want to see the output use print()

Casting User-Provided Numbers to Integers and Floats in Python

I'm trying to create a change return program that takes in a cost of an item and the money given and returns the proper change in terms of notes, quarters, dimes, etc.
I'm fairly new to programming and I'm stuck on trying to split it up. I've looked on StackOverflow and found the method math.modf(x) to be relevant. However, I am having a hard time implementing it.
Can you please let me know why change and y is not defined?
Thanks
import math
def changereturn():
quarter = 0.25
dime = 0.1
nickel = 0.05
penny = 0.01
cost = float(raw_input('Please enter the cost of the item in USD: '))
money = float(raw_input('Please enter the amount of money given in USD: '))
change = money - cost
y = math.modf(change)
return change
return y
A function (def) can only return one time, but python allows you to return tuples for result.
This implementation may be what you need:
import math
def changereturn():
quarter = 0.25
dime = 0.1
nickel = 0.05
penny = 0.01
cost = float(input('Please enter the cost of the item in USD: '))
money = float(input('Please enter the amount of money given in USD: '))
change = money - cost
y = math.modf(change)
return change, y
print(changereturn())
First issue is you never run your changereturn() function. Second issue is the two return lines in the changereturn() function. The second function which sends the y will never be run. You can return (change, y) and run your program as:
change, y = changereturn()
print change
print y
You need to put this at the very bottom without indenting. Personally, I don't like returning multiple things from a function. Normally I'd suggest catching it as a tuple and then printing each portion. Your question feels a bit like an assignment for a Comp Sci first year student so I don't want to 1)solve it for you and 2) make it overly complex.

Python3 about Loops Iteration multiple variable simple algorithm

What i have to do is have T number of test cases which is how many time i will
obtain the average of "n" number of students in each test case and i need to display the average score for each test case and the highest mark in that test case and the name of student
If you can tell me the proper way to code this and explain why it has to be that way i will greatly appreciate it! I am lost
My code:
t = int(input("enter number of cases: "))
def casing(t):
for case in range (1, t+1):
n = int(input("enter number of students: "))
def studentmarks(n):
total = 0
student = "none"
for computetotal in range(1,n+1):
student = input("please enter student name: ")
mark = int(input("please enter mark: "))
total = total+ mark
highestmark = mark
if studentmark(n) > mark:
highestmark = mark
achieve = student
return highestmark, acheive
return total, studentmark()[0], studentmark()[1]
average = float((studentmarks(n)[0])/ n)
print("average: ", average, "highest: ",studentmark(n)[1], "student: ", studentmark(n)[2])
I think the code, as it is, would be much simpler to understand and debug without the function declarations. Unless you're doing functional-style programming (e.g. passing around function objects) there's rarely a good reason to use nested functions. Here you're defining the functions, then immediately calling them once, which is fairly pointless. So here's a simplified version of your code:
t = int(input("enter number of cases: "))
for _ in range (t):
total = 0
highest_mark = 0
best_student = "none"
n = int(input("enter number of students: "))
for _ in range(n):
student = input("please enter student name: ")
mark = int(input("please enter mark: "))
total = total+ mark
if mark > highestmark:
highestmark = mark
beststudent = student
average = total / n
print("average: {}, highest: {}, student: {}"
.format(average, highestmark beststudent))
I also eliminated the function named studentmark (with no "s") which your code was calling but never defined. I'm not sure if I correctly interpreted what it was supposed to be doing, but I think so. It certainly wouldn't have worked before.
There are a few reasons this isn't working - but the root cause seems to be because your highestmark is started off in the wrong place. It looks like you later expect the student name and mark to be in a tuple, which is a good idea - but you never actually make this tuple anywhere. So, make one, and call it highest - it replaces both the student and highestmark variables. Start it as None instead of "none" (which could actually be a valid student name!), so you have above the loop:
total = 0
highest = None
and change your "is this one higher than the highest" logic to this:
if highest is None or mark > highest[1]:
highest = (name, mark)
Read as "if there is no highest student yet, or this one has a higher mark than the current highest, this one is the highest". Then you'll want the return to be:
return total, highest[0], highest[1]
But, since you only have a small amount of data (enough that it is feasible to have a user type it in at a console), then you can simplify this logic quite a bit. Read all of the data for a particular test case into a list of (student, mark) tuples, and then use Python's builtins to do the calculations:
def studentmarks(n):
marks = []
for _ in range(n):
student = input("please enter student name: ")
mark = int(input("please enter mark: "))
marks.append(student, mark)
return marks
# Calculations
marks = studentmarks(5)
print('Average: ', sum(result[1] for result in marks)/len(marks))
print('Highest: ', max(marks, key=lambda s: s[1])
Seeding it with:
>>> marks
[('Fred', 4), ('Wilma', 10), ('Barney', 8), ('Wilma', 7), ('Pebbles', 6)]
Gives an average of 7.0, and a maximum of ('Wilma', 10).

Categories